Java supports file operations using the classes in the java.io package. File input/output comprises of operations like
- Create a file or directory
- Get the contents of a directory
- Read the contents of a file
- Write or append to a file
- Delete a file or a directory
It is possible to categorize the type of data written into and read from files into two categories: streams and characters. java.io package provides methods for both categories.
I/O With Characters
The text data written to or read from files is made of characters. The following classes are the most used ones while working with text I/O with files and directories in Java.
- java.io.File: The basic class representing a file or a directory at an abstract level. Java uses the File class to represent both files and directories. The most used methods are createNewFile(), isFile(), isDirectory(), list(), delete(), renameTo(), mkdir() and exists().
- java.io.FileReader: It is used to read the text content of a file at a lower level. A FileReader is generally wrapped by a higher-level reader class during the read operation, like BufferedReader. The most used methods are write(), flush() and close().
- java.io.BufferedReader: It is generally used as a higher-level wrapper to a lower-level reader like FileReader to make reading the contents of a file more efficient. The most commonly used methods are write(), flush(), newLine() and close()
- java.io.FileWriter: It is used to write text content to a file at a lower level. A FileWriter is generally wrapped by a higher-level writer class during the write operation, like BufferedWriter.
- java.io.BufferedWriter: It is generally used as a higher-level wrapper to a lower-level writer like FileWriter to make writing the contents of a file more efficient.
- java.io.PrintWriter: It is generally used as a higher-level wrapper to a lower-level writer like FileWriter and provides writing formatted content to the lower-level writer.
- java.io.Console: It is used to read input directly from the console and also print formatted text content on the console. It was introduced with Java 6.
Now, let’s see how I/O operations with characters work in an example.
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MyClass {
public static void main(String [] args) {
File file = new File(“C:\\java_examples\io”);
if (file.exists()) {
file.delete();
}
file.mkdirs();
System.out.println(file.isDirectory());
file = new File(“C:\\java_examples\io\example1.txt”);
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
System.out.println(file.isFile());
BufferedWriter bufferedWriter = null;
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(file);
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(“Hello World.\r\n”);
bufferedWriter.write(“This message is from a friend.”);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
} finally {
try {
bufferedWriter.close();
} catch (IOException exception) {
exception.printStackTrace();
System.exit(1);
}
}
}
}
Inside the main method, first, a high level File object is created, pointing to a directory. Then, it is checked whether the file exists, using the exists() method and it is deleted using the delete() method. This is done to ensure that the directory is created from scratch every time this program runs. Following that, the directory is created from the file, using mkdirs() method. The check for the file being a directory, using isDirectory() method, returns true. Then the File object is initialized again, pointing to a file under the directory just created and then a file is created using createNewFile() method. The check whether the file is indeed a file, isFile() method is used which returns true in this case. Then we create a FileWriter object with the File just created, create a BufferedWriterWrapper around it, and then using BufferedWriter’s write method, we write text content to the file. In the end, bufferedWriter is closed.
Here, when we look at the code, we see that much of the code is inside try/catch blocks. This is because the methods used inside those blocks throw IOException. In addition, it is essential to close the BufferedWriter at the end of the write process. This is done in the finally block for guaranteed running. BufferedWriter’s close method throws IOException, too, so, a try/catch blocks is required inside the finally block as well.
Now, let’s see how we can read the content from the file we just created.
public class MyClass {
public static void main(String [] args) {
File file = new File(“C:\\java_examples\io\example1.txt”);
BufferedReader bufferedReader = null;
FileReader fileReader = null;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
String s = null;
while ((s = bufferedReader.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
} finally {
try {
bufferedReader.close();
} catch (IOException exception) {
exception.printStackTrace();
System.exit(1);
}
}
}
}
The output would be
Hello World
This message is from a friend
Here, again a File object pointing to the file that we would like to read is initialized. Then, a FileReader object is created with using the File object, and a BufferedReader is created as a wrapper around it. BufferedReader’s readLine() method reads the file line by line. Each line is kept in the String variable named s and then it is printed on the console.
Just like writer methods, reader methods throw IOException and need to be inside a try/catch block. Once the reading operation is over, the BufferedReader should be closed and as a best practice, this is done in the finally block.