Thursday, October 13, 2011

Java File Handling



Lately I been working on a Java file manipulation project and I came across an issue which I never expected.

This is a sample code.

public class FileReader {

    public static void main(String[] args) throws IOException {
        new FileReader().fileDelete();
    }

    public void fileDelete() throws IOException {

        final String fileLocation = System.getProperty("user.dir") + "/test.txt";

        File fileCreate = new File(fileLocation);
        final boolean isFileCreated = fileCreate.createNewFile();

        if (isFileCreated) {
            System.out.println("File Successfully Created");
        } else {
            System.out.println("File Creation Failed");
        }

        final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(fileLocation));
        for (int i = 1; i <= 5; i++) {
            bufferedWriter.append("Line : " + i + "\n");
        }

        final BufferedReader bufferedReader = new BufferedReader(new java.io.FileReader(fileLocation));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }

        File fileDelete = new File(fileLocation);
        final boolean isDeleteSuccess = fileDelete.delete();

        if (isDeleteSuccess) {
            System.out.println("File Deleted Successfully");
        } else {
            System.out.println("File Deletion Failed");
        }
    }
}
Assume the file test.txt does not exists when running the programme. Can you predict the output of this programme? 
If you have thought it will print

File Successfully Created
Line : 1
Line : 2
Line : 3
Line : 4
Line : 5
File Deleted Successfully


If you have thought a bit more you might have predicted it will print

File Successfully Created
File Deleted Successfully



You’re completely wrong at least on a Windows, both the above outputs are wrong. Actual output on windows is "File Deletion Failed". It took me some time to actually realize the issue when my programme dint work as expected. As for the part of the Line 1 .. 5 not printing that’s straight forward I dint close the bufferedWriter. The problem here is that if you read or write to a file and you don’t close the stream you cannot delete the file in windows. Even when you’re actually creating a new File object it will still not let you delete the file and to make things worse it does not give you any other explanation except for Boolean false Imagine searching for this in thousands of line. So guys whenever you’re reading or writing to streams always remember to close them.

5 comments:

  1. File Stream is just an handle and until any handle open to a physical file you can not delete it isn't it ? Thanks for putting this in a post to make it more obvious.

    Thanks
    Javin
    10 tips on java debugging with eclipse

    ReplyDelete
  2. Java 7 comes with auto-closable interface especially handy for these kind of problems.

    ReplyDelete
  3. That's only a Windows issue. Maybe with Windows 10 we can finally get over the single-user DOS-era.

    As I tested my Java application in Windows XP (I'm using only Linux) I had the issue that you can't open a file for read and write access even from the same process/program.

    In Linux it's no problem to open a file (like a serial port device) two times, one for read and one for write access. But in Windows you can open it only one time.

    ReplyDelete
  4. The issue is likely solved by using the try with resources functionality which is included in JDK7. InputStream and OutputStream implement AutoCloseable which guarantees that the streams are closed and the resources are released.

    ReplyDelete
  5. The new file system API (java.nio.file) does not suffer from this problem because it opens files on Windows with the DOS sharing mode set to allow delete (there are also provider specific options to allow you specify the DOS sharing mode). So in the above then try Files.newBufferedReader and Files.newBufferedWriter and see how you get on.

    ReplyDelete