Tuesday, 14 October 2014

File I/O

Let's review the classes allowing to manage the input/output operations on a file:
  • File
  • FileReader and FileWriter
  • BufferedReader and BufferedWriter
  • PrintWriter

File


The class "File" is a representation of a file or directory. Note that it does not represent the data in a file, it does not allow to read or write into a file.

With a "File" object you can:
  • make a new empty file or directory
  • list the names of the files contained in a directory
  • delete files or directories; note that if a directory is not empty then it can not be deleted
  • work with paths

Check if a file exists:
File myFile = new File("/etc/passwd");
System.out.println("File exists: "+myFile.exists());  // Output "File exists: true"

Create a new File:
    File myFile = new File("/tmp/testFile.tmp");               // This does not create a new file!
    System.out.println("File exists: "+myFile.exists());
   
    boolean isFileCreated = false;
    try{
        isFileCreated = myFile.createNewFile();                // This creates a new file

    }catch(java.io.IOException ex){
        System.out.println("IOException: "+ex.getMessage());
    }
    System.out.println("File created: "+isFileCreated);
    System.out.println("File exists: "+myFile.exists());   
Output:
File exists: false
File created: true
File exists: true

Create a new directory:
    File myDir = new File("/tmp/testDirectory");                      // This does not create a new directory!
    System.out.println("Directory exists: "+myDir.exists());   

    // We create a new directory
    boolean isDirectoryCreated = myDir.mkdir();
   
    System.out.println("Directory created: "+isDirectoryCreated);
    System.out.println("Directory exists: "+myDir.exists());
Output:
Directory exists: false
Directory created: true
Directory exists: true

Delete a file or a directory:
    boolean isFileDeleted = false;
    boolean isDirectoryDeleted = false;

    // Refer to a file
    File myFile = new File("/tmp/testFile.tmp");

    // Refer to a directory
    File myDir = new File("/tmp/testDirectory");

    // We delete a file
    if(myFile.exists()){
        isFileDeleted = myFile.delete();
    }

    // We delete a directory
    if(myDir.exists()){
        isDirectoryDeleted = myDir.delete();
    }

    System.out.println("File deleted: "+isFileDeleted);
    System.out.println("Directory deleted: "+isDirectoryDeleted);
Output:
File deleted: true
Directory deleted: true

List files contained in a directory:
    File tmpDir = new File("/tmp");
   
    for(String fileName : tmpDir.list()){
        System.out.println("- "+fileName);
    }
Output:
- tmp.FZrqYV5538
- .esd-1000
- a.cc06n7
...

FileReader and FileWriter


"FileReader" and "FileWriter" are low level API classes which allow to read/write data from/to a file. As their API is low level, you will usually use a "FileReader" object by injecting it into a "BufferedReader" object. In same way, you will usually use a "FileWriter" object by injecting it into either a "BufferedWriter" object or a "PrintWriter" object.

Their constructors can accept a "File" object or a String object with the value of file's path.

Eg.
    File myFile = new File("/etc/passwd");

    try{
        FileReader fileReader = new FileReader(myFile);
       fileReader.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException: "+ex.getMessage());
    }

Or:
    try{
       FileReader fileReader = new FileReader("/etc/passwd");
        fileReader.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException: "+ex.getMessage());
    }

Write in a file with "FileWriter":
    // Lignes to write
    String[] lignesToWrite = {"This is line 1", "This is line 2", "This is line 3"};

    try{
        // If the file does not exist then it will create it
        // If the file exists then it clear its contents
        FileWriter fileWriter = new FileWriter("/tmp/testFile.tmp");

        // We write in the file
        for(String ligneToWrite : lignesToWrite){
           fileWriter.write(ligneToWrite + System.getProperty("line.separator"));
        }

        // Flush the contents written in the file and then close the stream
        fileWriter.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException while writting: "+ex.getMessage());
    }

Read a file's contents with "FileReader":
    try{
        // We open the file to read
        FileReader fileReader = new FileReader("/tmp/testFile.tmp");

        // We read the file character by character until the end of the file.
        // Note that "fileReader.read()" returns "-1" if the end of the file has been reached.
        int characterToRead = 0;
        while( (characterToRead = fileReader.read()) != -1){
            System.out.print((char)characterToRead);
        }

        // We close the stream
        fileReader.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException while reading: "+ex.getMessage());
    }
Output:
File's contents:
This is line 1
This is line 2
This is line 3

BufferedReader and BufferedWriter


"BufferedReader" and "BufferedWriter" are high level API classes which allow to read/write data from/to a file. They are easier to use and offer better performance than the classes "FileReader" and "FileWriter" especially when the program has to manipulate a large chunk of data (they use an efficient buffer mechanism).

Note that the constructor of "BufferedReader" accept only a subtype of the abstract class "Reader" and the constructor "BufferedWriter" accept only a subtype of the abstract class "Writer".

Write in a file with "BufferedWriter":
    // Lignes to write
    String[] lignesToWrite = {"This is line 1", "This is line 2", "This is line 3"};

    try{
        // "BufferedWriter" needs a subtype of the abstract class "Writer"
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("/tmp/testFile.tmp"));

        // We write in the file
        for(String ligneToWrite : lignesToWrite){
            bufferedWriter.write(ligneToWrite);
          bufferedWriter.newLine();
        }

        // Flush the contents written in the file and then close the stream
        bufferedWriter.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException while writting: "+ex.getMessage());
    }

Read a file's contents with "BufferedReader":
    try{
        // "BufferedReader" needs a subtype of the abstract class "Reader"
        BufferedReader bufferedReader = new BufferedReader(new FileReader("/tmp/testFile.tmp"));

        // We read the file line by line until the end of the file
        // Note that "bufferedReader.readLine()" returns "null" if the end of the file has been reached.
        String ligneToRead = null;
        while( (ligneToRead = bufferedReader.readLine()) != null){
            System.out.println(ligneToRead);
        }

        // We close the stream
        bufferedReader.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException while reading: "+ex.getMessage());
    }

PrintWriter


"PrintWriter" has been improved significantly in Java 5. It has an easier usage than "BufferWriter" and has better performance. Its constructor is very flexible, it can be instantiated with:
  • a String object which contains the value of a file's path
  • a "File" object
  • a subtype of the abstract class "Writer"

Eg.
    // Lignes to write
    String[] lignesToWrite = {"This is line 1", "This is line 2", "This is line 3"};

    try{
        // If the file does not exist then it will create it
        // If the file exists then it clear its contents
        PrintWriter printWriter = new PrintWriter("/tmp/testFile.tmp");

        // We write in the file
        for(String ligneToWrite : lignesToWrite){
            printWriter.println(ligneToWrite);                // Add automatically a new carriage return line ('\n', ...)
        }

        // Flush the contents written in the file and then close the stream
        printWriter.close();

    }catch(java.io.IOException ex){
        System.out.println("IOException while writting: "+ex.getMessage());
    }