I'm trying to use the following code to access one byte with offset of 50 bytes in a raw disk.
randomAccessFile = new RandomAccessFile("C:", "r");
randomAccessFile.seek(50);
byte[] buffer = new byte[1];
randomAccessFile.read(buffer);
But all what I get is the following error:
java.io.FileNotFoundException: C: (Acceso denegado)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:212)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:98)
at pru.lseek.main(lseek.java:26)
Is there any way to access a precise byte in a drive from java?
I was looking by myself for a possibility to access raw data form a physical drive. And now as I got it to work, I just want to tell you how. You can access raw disk data directly from within java ... just run the following code with administrator priviliges:
File diskRoot = new File ("\\\\.\\PhysicalDrive0");
RandomAccessFile diskAccess = new RandomAccessFile (diskRoot, "r");
byte[] content = new byte[1024];
diskAccess.readFully (content);
So you will get the first kB of your first physical drive on the system. To access logical drives - as mentioned above - just replace 'PhysicalDrive0' with the drive letter e.g. 'D:'
oh yes ... I tried with Java 1.7 on a Win 7 system ...
Just have a look at the naming of physical drives at http://support.microsoft.com/kb/100027/en-us
If you are interested in writing to a raw volume under Windows, try this (needs Java 7).
String pathname;
// Full drive:
// pathname = "\\\\.\\PhysicalDrive0";
// A partition (also works if windows doesn't recognize it):
pathname = "\\\\.\\GLOBALROOT\\ArcName\\multi(0)disk(0)rdisk(0)partition(5)";
Path diskRoot = ( new File( pathname ) ).toPath();
FileChannel fc = FileChannel.open( diskRoot, StandardOpenOption.READ,
StandardOpenOption.WRITE );
ByteBuffer bb = ByteBuffer.allocate( 4096 );
fc.position( 4096 );
fc.read( bb );
fc.position( 4096 );
//fc.write( bb ); // careful!
fc.close();
Of course, you have to make sure the device is writable and not accessed/locked by the system. Also make sure your application runs with the necessary privileges (elevated privileges).
Btw: Using new RandomAccessFile(drive, "rw") doesn't seem to work because Java doesn't open the file handle in a mode which is compatible to raw devices (exception is java.io.FileNotFoundException (The parameter is incorrect)). But reading works fine also with RandomAccessFile.
RandomAccessFile is not meant to open directories to manipulate entries, you need to create or remove files. "Acceso denegado" probably mean access denied.
To do this anyway you need JNI.
EDIT: What you are trying to do, is really complicated, there is no common way to do that. You can access the harddisc sector by sector, but then you would have to interpret it's structure, which obviously depends on the file system, FAT,NTFS,HPFS etc.
Under Linux you can try to open /dev/<device>, e.g. /dev/hda, or /dev/sdb2. This will give you access to a raw disk (or a partition only) but requires that you have appropriate rights—a “normal” user does not have them, though.
Java can only access files. Unix has the concept of "raw devices" as files in the /dev directory, so what you want is possible there. But not on windows, because it has no such file representation of the raw HD data.
In windows you need to access the raw device identifier as a file. It should work if you pass in the file "\\.\c:", you are using the device UNC name \.\c: (\. means this machine).
For Vista and later I don't think it will work correctly as there are mechanisms in place to prevent raw access to the disk for anything other than device drivers (don't quote me on that)
#hunsricker : note that accessing raw devices require some privileges (depends on drive : removable or not / depends on file system for WinXP : iso9660 is allowed, FAT is not).
Note also that size of read does matter (depending on OS) :
On an iso9660 filesystem, read(1024 bytes) works on XP but fails on Seven.
On Seven it look like the reads must be block aligned : read(2048 bytes) works.
In unix, you may read/write from /dev files. (I'm not sure)
In Windows, I think you need to read/write disk sectors via JNI(Java Native Interface). Calls some C library to talk to the OS.
update: In C library, you may need to use Win32API to get the file handle for example CreateFile(..) function.
https://metacpan.org/pod/Win32API::File
http://jan.newmarch.name/ssw/files/win32.html
Related
Asked this question, having already tried possible solutions in other questions here on stack but that didn't allow me to fix the problem.
As in the title, I have created a java utility with which I have to perform operations on text files, in particular I have to perform simple operations to move between directories, copy from one directory to another, etc.
To do this I have used the java libraries java.io.File and java.nio.*, And I have implemented two functions for now,copyFile(sourcePath, targetPath) and moveFile(sourcePath, targetPath).
To develop this I am using a mac, and the files are under the source path /Users/myname/Documents/myfolder/F24/archive/, and my target path is /Users/myname/Documents/myfolder/F24/target/.
But when I run my code I get a java.nio.file.NoSuchFileException: /Users/myname/Documents/myfolder/F24/archive
Having tried the other solutions here on stack and java documentation already I haven't been able to fix this yet ... I accept any advice or suggestion
Thank you all
my code:
// copyFile: funzione chiamata per copiare file
public static boolean copyFile(String sourcePath, String targetPath){
boolean fileCopied = true;
try{
Files.copy(Paths.get(sourcePath), Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
}catch(Exception e){
String sp = Paths.get(sourcePath)+"/";
fileCopied = false;
System.out.println("Non posso copiare i file dalla cartella "+sp+" nella cartella "+Paths.get(targetPath)+" ! \n");
e.printStackTrace();
}
return fileCopied;
}
Files.copy cannot copy entire directories. The first 'path' you pass to Files.copy must ALL:
Exist.
Be readable by the process that runs the JVM. This is non-trivial on a mac, which denies pretty much all disk rights to all apps by default until you give it access. This can be tricky for java apps. I'm not quite sure how you fix it (I did something on my mac to get rid of that, but I can't remember what - possibly out of the box java apps just get to read whatever they want and it's only actual mac apps that get pseudo-sandboxed. Point is, there's a chance it's mac's app access control denying it even if the unix file rights on this thing indicate you ought to be able to read it).
Be a plain old file and not a directory or whatnot.
Files.move can (usually - depends on impl and underlying OS) usually be done to directories, but not Files.copy. You're in a programming language, not a shell. If you want to copy entire directories, write code that does this.
Not sure whether my comment is understood though answered.
Ìn java SE target must not be the target directory. In other APIs of file copying
one can say COPY FILE TO DIRECTORY. In java not so; this was intentionally designed to remove one error cause.
That style would be:
Path source = Paths.get(sourcePath);
if (Files.isRegularFile(source)) {
Path target = Paths.get(targetPath);
Files.createDirectories(target);
if (Files.isDirectory(target)) {
target = Paths.get(targetPath, source.getFileName().toString());
// Or: target = target.resolve(source.getFileName().toString());
}
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
}
Better ensure when calling to use the full path.
Do I can open a file (linux character device) for read+write, and use the two classes to implement a dialog like client-server?
Something like this:
File file = new File("/dev/ttyS0");
FileOutpuStream fo = new FileOutputStream(file)
FileInputStream fi = new FileInputStream(file)
After the above declarations, can I continuously send pollings (questions) to the file, and read its replies? (Of course, attached to ttyS0 there is a kind of server)
I was not able to test it, but you might want to give RandomAccessFile a try.
It does not give you the opertunity to create streams, but it implements DataInput and DataOutput. Thats maybe good enough for your purpose?
RandomAccessFile docs
String file = "/dev/ttyS0";
try {
RandomAccessFile f = new RandomAccessFile(file, "rwd");
} catch (IOException e){
e.printStackTrace();
}
The /dev/ttyS0 file is a device file for a serial terminal.
If the device has been configured appropriately to connect to a serial terminal line, then you should be able to read and write like that. However, on a typical desktop or laptop, it probably won't work because there won't be connected serial line.
(For example, when I do this on my PC:
$ sudo bash -c "cat < /dev/ttyS0"
I get this:
cat: -: Input/output error
which is saying that the device cannot be read from.)
Note that a /dev/tty* device does not behave like a regular file. The characters that are written in no way relate to the characters that you read back. Also note that it is not possible to make ioctl requests using the standard Java APIs. So configuring the terminal driver from Java would be problematic.
If you were talking abour reading and writing a regular file, it should work too. However, the behavior could be a rather confusing, especially if you have buffering in your streams. One issue you need to deal with is that the two file descriptors are independent of each other.
If you need to do this kind of thing with a regular file, you should probably use RandomAccessFile.
I didn't try RandomAccessFile, it could also work... it worked smoothly with FileInputStream and FileOutputStream, see this answer in SO: https://stackoverflow.com/a/56935267/7332147
I am creating a web application which will allow the upload of shape files for use later on in the program. I want to be able to read an uploaded shapefile into memory and extract some information from it without doing any explicit writing to the disk. The framework I am using (play-framework) automatically writes a temporary file to the disk when a file is uploaded, but it nicely handles the creation and deletion of said file for me. This file does not have any extension, however, so the traditional means of reading a shapefile via Geotools, like this
public void readInShpAndDoStuff(File the_upload){
Map<String, Serializable> map = new HashMap<>();
map.put( "url", the_upload.toURI().toURL() );
DataStore dataStore = DataStoreFinder.getDataStore( map );
}
fails with an exception which states
NAME_OF_TMP_FILE_HERE is not one of the files types that is known to be associated with a shapefile
After looking at the source of Geotools I see that the file type is checked by looking at the file extension, and since this is a tmp file it has none. (Running file FILENAME shows that the OS recognizes this file as a shapefile).
So at long last my question is, is there a way to read in the shapefile without specifying the Url? Some function or constructor which takes a File object as the argument and doesn't rely on a path? Or is it too much trouble and I should just save a copy on the disk? The latter option is not preferable, since this will likely be operating on a VM server at some point and I don't want to deal with file system specific stuff.
Thanks in advance for any help!
I can't see how this is going to work for you, a shapefile (despite it's name) is a group of 3 (or more) files which share a basename and have extensions of .shp, .dbf, .sbx (and usually .prj, .sbn, .fix, .qix etc).
Is there someway to make play write the extensions with the tempfile name?
I'm working on a microcontroller and I'm trying to write some data from some sensors into a .txt file on the SDcard and later on place the sd card in a card reader and read the data on the PC.
Does anyone know how to write a .txt file from scratch for a FAT32 file system? I don't have any predefined code/methods/functions to call, I'll need to create the code from nothin.
It's not a question for a specific programming language, that is why I tagged more than one. I can later on convert the code from C or Java to my programming language of choice. But I can't seem to find such low level methods/functions in any type of language :)
Any ideas?
FatFs is quite good, and highly portable. It has support for FAT12, FAT16 and FAT32, long filenames, seeking, reading and writing (most of these things can be switched on and off to change the memory footprint).
If you're really tight on memory there's also Petit FatFs, but it doesn't have write support by default and adding it would take some work.
After mounting the drive you'd simply open a file to create it. For example:
FATFS fatFs;
FIL newFile;
// The drive number may differ
if (f_mount(0, &fatFs) != FR_OK) {
// Something went wrong
}
if (f_open(&newFile, "/test.txt", FA_WRITE | FA_OPEN_ALWAYS) != FR_OK) {
// Something went wrong
}
If you really need to create the file using only your own code you'll have to traverse the FAT, looking for empty space and then creating new LFN entries (where you store the filename) and DIRENTs (which specify the clusters on the disk that will hold the file data).I can't see any reason for doing this except if this is some kind of homework / lab exercise. In any case you should do some reading about the FAT structure first and return with some more specific questions once you've got started.
In JAVA you can do like this
Writer output = null;
String text = "This is test message";
File file = new File("write.txt");
output = new BufferedWriter(new FileWriter(file));
output.write(text);
output.close();
System.out.println("Your file has been written");
In my application I need to save some file (a pdf) to the filesystem. My current method involves creating a directory for storing the files:
FileConnection fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/pdfs/");
if (!fc.exists())
fc.mkdir();
fc.close();
I then write to the directory with my file:
fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/pdfs/" + filename, Connector.READ_WRITE);
if (!fc.exists())
fc.create();
OutputStream outStream = fc.openOutputStream();
outStream.write(pdf);
outStream.close();
fc.close();
This all works fine, and my pdf arrives in my created directory. My question is: will I run into trouble with the fact that I have hard coded a file path as my save destination. With the BlackBerry API is it possible to retrieve a writeable folder which exists on all models/configurations?
You can query the system for the available roots using FileSystemRegistry.listRoots(). Note that it is not guaranteed that there will be an sdcard, or that it will be visible even if there is one (when in mass storage mode, for instance). I think that the only root guaranteed to be on all devices is internal storage ("file:///Store").
There's (a little) more information here.