Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete file after staring connection using FileInputStream

I have a temporary file which I want to send the client from the controller in the Play Framework. Can I delete the file after opening a connection using FileInputStream? For example can I do something like this -

File file = getFile();
InputStream is = new FileInputStream(file);
file.delete();
renderBinary(is, "name.txt");

What if file is a large file? If I delete the file, will subsequent reads() on InputStream give an error? I have tried with files of around 1MB I don't get an error.

Sorry if this is a very naive question, but I could not find anything related to this and I am pretty new to Java

like image 517
Poojan Avatar asked Sep 19 '13 06:09

Poojan


People also ask

How to delete file using path in Java?

In Java, we can delete a file by using the File. delete() method of File class. The delete() method deletes the file or directory denoted by the abstract pathname. If the pathname is a directory, that directory must be empty to delete.

How to delete a opened file in Java?

a.delete() method is the method of the File class of Java. This method deletes the file from the system. Its return type is boolean. It will return true if the file is deleted and false if the delete operation fails.

How do you delete a file if already exists in Java?

files. deleteifexists(Path p) method defined in Files package: This method deletes a file if it exists. It also deletes a directory mentioned in the path only if the directory is not empty. Returns: It returns true if the file was deleted by this method; false if it could not be deleted because it did not exist.

How to read file from FileInputStream in Java?

FileInputStream input = new FileInputStream("input. txt"); To read data from the file, we have used the read() method inside the while loop.


2 Answers

I just encountered this exact same scenario in some code I was asked to work on. The programmer was creating a temp file, getting an input stream on it, deleting the temp file and then calling renderBinary. It seems to work fine even for very large files, even into the gigabytes.

I was surprised by this and am still looking for some documentation that indicates why this works.

UPDATE: We did finally encounter a file that caused this thing to bomb. I think it was over 3 Gb. At that point, it became necessary to NOT delete the file while the rendering was in process. I actually ended up using the Amazon Queue service to queue up messages for these files. The messages are then retrieved by a scheduled deletion job. Works out nicely, even with clustered servers on a load balancer.

like image 112
Jeremy Goodell Avatar answered Oct 23 '22 19:10

Jeremy Goodell


It seems counter-intuitive that the FileInputStream can still read after the file is removed.

DiskLruCache, a popular library in the Android world originating from the libcore of the Android platform, even relies on this "feature", as follows:

// Open all streams eagerly to guarantee that we see a single published
// snapshot. If we opened streams lazily then the streams could come
// from different edits.
InputStream[] ins = new InputStream[valueCount];
try {
  for (int i = 0; i < valueCount; i++) {
    ins[i] = new FileInputStream(entry.getCleanFile(i));
  }
} catch (FileNotFoundException e) {
....

As @EJP pointed out in his comment on a similar question, "That's how Unix and Linux behave. Deleting a file is really deleting its name from the directory: the inode and the data persist while any processes have it open."

But I don't think it is a good idea to rely on it.

like image 32
Haoming Avatar answered Oct 23 '22 20:10

Haoming