is there a way to open a directory stream in Java like in C? I need a FileDescriptor of an opened directory. Well, actually just the number of the fd.
I try to implement a checkpoint/restore functionality in Java with the help of CRIU link. To do this, I need to deploy a RPC call to the CRIU service. There I have to provide the integer value of the FD of an already opened directory, where the image files of the process will be stored.
Thank you in advance!
is there a way to open a directory stream in Java like in C?
No there isn't. Not without resorting to native code.
If you want to "read" a directory in (pure) Java, you can do it using one of the following:
File.list() - gives you the names of the directory entries as strings.
File.list(FilenameFilter) - ditto, but only directory entries that match are returned.
File.listFiles() - like list() but returning File objects.
etcetera
Files.newDirectoryStream(Path) gives you an iterator for the Path objects for the entries in a directory.
The last one could be "close" to what you are trying to achieve, but it does not entail application code getting hold of a file descriptor for a directory, or the application doing a low-level "read" on the directory.
You don't need FD in Java. All you need is a reference to that file which you can simply acquire using File file = new File("PathToYourFile");
To read/write you have Streams in Java. You can use
BufferedReader fileReader = new BufferedReader(new FileReader(new File("myFile.txt")));
PrintWriter fileWriter = new PrintWriter(new FileWriter(new File("myFile.txt")));
Even directory is a file. You can use isDirectory() on file object to check if it is a directory or a file.
private FileDescriptor openFile(String path)
throws FileNotFoundException, IOException {
File file = new File(path);
FileOutputStream fos = new FileOutputStream(file);
// remember th 'fos' reference somewhere for later closing it
fos.write((new Date() + " Beginning of process...").getBytes());
return fos.getFD();
}
Related
Whenever the next segment of code is run, I get the new csv file created, but I don't get anything written to it:
PrintWriter fout = null;
try {
// create file
fout= new PrintWriter("EEGLogger.csv");
String headerFile = "IED_COUNTER, IED_INTERPOLATED, IED_RAW_CQ, IED_AF3, IED_F7, IED_F3, IED_FC5, IED_T7, " +
"IED_P7, IED_O1, IED_O2, IED_P8, IED_T8, IED_FC6, IED_F4, IED_F8, IED_AF4, " +
"IED_GYROX, IED_GYROY,IED_TIMESTAMP";
// Writes the header to the file
fout.println(headerFile);
fout.println();
...
I do a fout.close() in a finally statement, but that still doesn't help get any output to the file. Any ideas here?
Either:
You are looking in the wrong place, i.e. not the current working directory, or
You don't have write access to the current working directory.
If you had used a FileWriter and not got an IOException, that would rule out (2).
I've seen about a million answers and comments here this week claiming that the current working directory equals the location of the JAR file, but it doesn't.
You could open a FileWriter
fout = new PrintWriter(new FileWriter("EEGLogger.csv"));
...
fout.flush();
fout.close()
I believe the PrintWriter is intended for formatting and character encoding. api docs states Prints formatted representations of objects to a text-output stream and as well Methods in this class never throw I/O exceptions.
Using the FileWriter as parameter would force you to handle any IOException that may happen so if the file is not created or not writable, you will immediately get this information.
Another situation can happen if the file is created and you are just looking for the file at incorrect location. I'd suggest to create a File object too, to see where the file really resides (what's your real working directory)
File f = new File("EEGLogger.csv");
fout = new PrintWriter(new FileWriter(f));
System.out.println(f.getAbsolutePath());
I am trying to open a file for reading or create the file if it was not there.
I use this code:
String location = "/test1/test2/test3/";
new File(location).mkdirs();
location += "fileName.properties";
Path confDir = Paths.get(location);
InputStream in = Files.newInputStream(confDir, StandardOpenOption.CREATE);
in.close();
And I get java.nio.file.NoSuchFileException
Considering that I am using StandardOpenOption.CREATE option, the file should be created if it is not there.
Any idea why I am getting this exception?
It seems that you want one of two quite separate things to happen:
If the file exists, read it; or
If the file does not exist, create it.
The two things are mutually exclusive but you seem to have confusingly merged them. If the file did not exist and you've just created it, there's no point in reading it. So keep the two things separate:
Path confDir = Paths.get("/test1/test2/test3");
Files.createDirectories(confDir);
Path confFile = confDir.resolve("filename.properties");
if (Files.exists(confFile))
try (InputStream in = Files.newInputStream(confFile)) {
// Use the InputStream...
}
else
Files.createFile(confFile);
Notice also that it's better to use "try-with-resources" instead of manually closing the InputStream.
Accordingly to the JavaDocs you should have used newOutputStream() method instead, and then you will create the file:
OutputStream out = Files.newOutputStream(confDir, StandardOpenOption.CREATE);
out.close();
JavaDocs:
// Opens a file, returning an input stream to read from the file.
static InputStream newInputStream(Path path, OpenOption... options)
// Opens or creates a file, returning an output stream that
// may be used to write bytes to the file.
static OutputStream newOutputStream(Path path, OpenOption... options)
The explanation is that OpenOption constants usage relies on wether you are going to use it within a write(output) stream or a read(input) stream. This explains why OpenOption.CREATE only works deliberatery with the OutputStream but not with InputStream.
NOTE: I agree with #EJP, you should take a look to Oracle's tutorials to create files properly.
I think you intended to create an OutputStream (for writing to) instead of an InputStream (which is for reading)
Another handy way of creating an empty file is using apache-commons FileUtils like this
FileUtils.touch(new File("/test1/test2/test3/fileName.properties"));
I am new to programming, I need help in understanding the difference between 2 ways of creating a fileinputstream object for reading files. I have seen examples on internet, some have used first one and others second one. I am confused which is better and why?
FileInputStream file = new FileInputStream(new File(path));
FileInputStream file = new FileInputStream(path);
Both are fine. The second one calls the first implicitly.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
If you have a reference to the file which should be read, use the former. Else, you should probably use the latter (if you only have the path).
Don't use either in 2015. Use Files.newInputStream() instead. In a try-with-resources statement, at that:
final Path path = Paths.get("path/to/file");
try (
final InputStream in = Files.newInputStream(path);
) {
// do stuff with "in"
}
More generally, don't use anything File in new code in 2015 if you can avoid it. JSR 203, aka NIO2, aka java.nio.file, is incomparably better than java.io.File. And it has been there since 2011.
The FileInputStream Class has three constructors. Described in the official documentation:
FileInputStream(File file)
Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system.
FileInputStream(String name)
Creates a FileInputStream by opening a connection to an actual file, the file named by the path name name in the file system.
FileInputStream(FileDescriptor fdObj)
Creates a FileInputStream by using the file descriptor fdObj, which represents an existing connection to an actual file in the file system.
As you see here there is no real difference.
Actually they both have the same way to open a file. The first constructor calls
SecurityManager.checkRead(File.getPath())
And the second one uses the same checkRead() as
SecurityManager.checkRead(name)
if you want use
FileInputStream file = new FileInputStream(new File(path));
for create FileInputStream need more time, if I don't mistake, because this constructor doing some checks with security manager
There is not much difference between the two , as
FileInputStream file = new FileInputStream(path)
implicitly calling other.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
But to make better use of two available constructors, we can use constructor taking File argument when there is already a File object so we will be avoiding creation of another file object which will be created implicitly If we are using another constructor
Secondly, It is better to create FileinputStream object only after checking the existence of file which can be checked by using file.exists() in that case we can avoid FileNotFoundException.
This question already has answers here:
How to read file from ZIP using InputStream?
(7 answers)
Closed 1 year ago.
How can I create new File (from java.io) in memory, not on the hard disk?
I am using the Java language. I don't want to save the file on the hard drive.
I'm faced with a bad API (java.util.jar.JarFile). It's expecting File file of String filename. I have no file (only byte[] content) and can create temporary file, but it's not beautiful solution. I need to validate the digest of a signed jar.
byte[] content = getContent();
File tempFile = File.createTempFile("tmp", ".tmp");
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(archiveContent);
JarFile jarFile = new JarFile(tempFile);
Manifest manifest = jarFile.getManifest();
Any examples of how to achieve getting manifest without creating a temporary file would be appreciated.
How can I create new File (from java.io) in memory , not in the hard disk?
Maybe you are confusing File and Stream:
A File is an abstract representation of file and directory pathnames. Using a File object, you can access the file metadata in a file system, and perform some operations on files on this filesystem, like delete or create the file. But the File class does not provide methods to read and write the file contents.
To read and write from a file, you are using a Stream object, like FileInputStream or FileOutputStream. These streams can be created from a File object and then be used to read from and write to the file.
You can create a stream based on a byte buffer which resides in memory, by using a ByteArrayInputStream and a ByteArrayOutputStream to read from and write to a byte buffer in a similar way you read and write from a file. The byte array contains the "File's" content. You do not need a File object then.
Both the File... and the ByteArray... streams inherit from java.io.OutputStream and java.io.InputStream, respectively, so that you can use the common superclass to hide whether you are reading from a file or from a byte array.
It is not possible to create a java.io.File that holds its content in (Java heap) memory *.
Instead, normally you would use a stream. To write to a stream, in memory, use:
OutputStream out = new ByteArrayOutputStream();
out.write(...);
But unfortunately, a stream can't be used as input for java.util.jar.JarFile, which as you mention can only use a File or a String containing the path to a valid JAR file. I believe using a temporary file like you currently do is the only option, unless you want to use a different API.
If you are okay using a different API, there is conveniently a class in the same package, named JarInputStream you can use. Simply wrap your archiveContent array in a ByteArrayInputStream, to read the contents of the JAR and extract the manifest:
try (JarInputStream stream = new JarInputStream(new ByteArrayInputStream(archiveContent))) {
Manifest manifest = stream.getManifest();
}
*) It's obviously possible to create a full file-system that resides in memory, like a RAM-disk, but that would still be "on disk" (and not in Java heap memory) as far as the Java process is concerned.
You could use an in-memory filesystem, such as Jimfs
Here's a usage example from their readme:
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path foo = fs.getPath("/foo");
Files.createDirectory(foo);
Path hello = foo.resolve("hello.txt"); // /foo/hello.txt
Files.write(hello, ImmutableList.of("hello world"), StandardCharsets.UTF_8);
I think temporary file can be another solution for that.
File tempFile = File.createTempFile(prefix, suffix, null);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteArray);
There is a an answer about that here.
I'm reading a bunch of files from an FTP. Then I need to unzip those files and write them to a fileshare.
I don't want to write the files first and then read them back and unzip them. I want to do it all in one go. Is that possible?
This is my code
FTPClient fileclient = new FTPClient();
..
ByteArrayOutputStream out = new ByteArrayOutputStream();
fileclient.retrieveFile(filename, out);
??????? //How do I get my out-stream into a File-object?
File file = new File(?);
ZipFile zipFile = new ZipFile(file,ZipFile.OPEN_READ);
Any ideas?
You should use a ZipInputStream wrapped around the InputStream returned from FTPClient's retrieveFileStream(String remote).
You don't need to create the File object.
If you want to save the file you should pipe the stream directly into a ZipOutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(out);
// do whatever with your zip file
If, instead, you want to open the just retrieved file work with the ZipInputStream:
new ZipInputStream(fileClient.retrieveFileStream(String remote));
Just read the doc here and here
I think you want:
ZipInputStream zis = new ZipInputStream( new ByteArrayInputStream( out.toByteArray() ) );
Then read your data from the ZipInputStream.
As others have pointed out, for what you are trying to do, you don't need to write the downloaded ZIP "file" to the file system at all.
Having said that, I'd like to point out a misconception in your question, that is also reflected in some of the answers.
In Java, a File object does no really represent a file at all. Rather, it represents a file name or *path". While this name or path often corresponds to an actual file, this doesn't need to be the case.
This may sound a bit like hair-splitting, but consider this scenario:
File dir = new File("/tmp/foo");
boolean isDirectory = dir.isDirectory();
if (isDirectory) {
// spend a long time computing some result
...
// create an output file in 'dir' containing the result
}
Now if instances of the File class represented objects in the file system, then you'd expect the code that creates the output file to succeed (modulo permissions). But in fact, the create could fail because, something deleted the "/tmp/foo", or replaced it with a regular file.
It must be said that some of the methods on the File class do seem to assume that the File object does correspond to a real filesystem entity. Examples are the methods for getting a file's size or timestamps, or for listing the names in a directory. However, in each case, the method is specified to throw an exception if the actual file does not exist or has the wrong type for the operation requested.
Well, you could just create a FileOutputStream and then write the data from that:
FileOutputStream fos = new FileOutputStream(filename);
try {
out.writeTo(fos);
} finally {
fos.close();
}
Then just create the File object:
File file = new File(filename);
You need to understand that a File object doesn't represent any real data on disk - it's just a filename, effectively. The file doesn't even have to exist. If you want to actually write data, that's what FileOutputStream is for.
EDIT: I've just spotted that you didn't want to write the data out first - but that's what you've got to do, if you're going to pass the file to something that expects a genuine file with data in.
If you don't want to do that, you'll have to use a different API which doesn't expect a file to exist... as per Qwerky's answer.
Just change the ByteArrayOutputStream to a FileOutputStream.