Reading from and writing to a file in Java #
There are numerous ways to read from or write to a file in Java, using either native of external libraries.
We highlight here some of the simplest ones (syntactically), even though they may not be the most efficient.
We also restrict our scope to:
- reading and writing text (but Java also offers multiple ways to read or write sequences of bytes),
- reading sequentially and writing by appending (but some classes like RandomAccessFile allow accessing any position in a file).
Reading #
Reading a text file line by line #
Here is one way to process the content of a text file line by line:
try (BufferedReader reader = Files.newBufferedReader(Path.of("path/to/file.txt"))){
String line = reader.readLine();
while (line != null){
System.out.println(line);
line = reader.readLine();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
Reading an entire text file #
Alternatively, if the file is small, its whole content can be stored as a list of strings (one per line), as follows:
List<String> lines;
try (Stream<String> stream = Files.lines(Path.of("path/to/file.txt"))){
lines = stream.toList();
} catch (IOException e) {
throw new RuntimeException(e);
}
Or even as a single string:
String text;
try {
text = Files.readString(Path.of("path/to/file.txt"));
} catch (IOException e) {
throw new RuntimeException(e);
}
Splitting #
The method String.split
can be used to decompose a string into an array of substring, based on some delimiter.
For instance, in a csv file, each line can be decomposed using a comma (,
), as follows:
String line = "Alice,Bob,Carol";
// Contains ["Alice", "Bob", "Carol"]
String[] names = line.split(",");
We will see in the chapter dedicated to regular expressions that more expressive delimiters can be used.
Reading with a scanner #
The class Scanner
is a versatile tool that allows reading from the standard input, but also from a file.
We refer to last year’s course for an overview.
Writing #
Warning. In Java, methods that write an (underspecified) line separator produce a (sequence of) character(s) that depends on the operating system running the program:
\r\n
on Windows, and\n
on most other modern operating systems.
This is the case in all three examples below, with the methods BufferedWriter.newLine
, PrintWriter.println
and Files.write
.
Writing incrementally #
A common way to write to a file consists in using a BufferredWriter
.
For instance:
try(BufferedWriter writer = Files.newBufferedWriter(Path.of("path/to/file.txt"))){
writer.write("Hi");
writer.newLine();
} catch (IOException e) {
e.printStackTrace();
}
A PrintWriter
offers additional methods to easily format the output, such as print
, println
or printf
, analogous to the methods of the standard output stream System.out
.
It is often used as a wrapper around another writer, for instance a BufferedWriter
:
try(PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Path.of("path/to/file.txt")))){
writer.println("Hi");
} catch (IOException e) {
e.printStackTrace();
}
Writing an entire list #
The method Files.write
can be used to write all elements of a list to a file (one per line):
List<String> strings = List.of("foo", "bar");
try {
Files.write(
Path.of("path/to/file.txt"),
strings
);
} catch (IOException e) {
throw new RuntimeException(e);
}
Writing a single string #
The method Files.writeString
can be used to write a single string to a file
try {
Files.writeString(
Path.of("path/to/file.txt"),
"foo"
);
} catch (IOException e) {
throw new RuntimeException(e);
}
Note that this will overwrite the content of the file.
Instead, in order to append a string to a file, a third argument can be added to the method Files.writeString
:
try {
Files.writeString(
Path.of("path/to/file.txt"),
"foo",
StandardOpenOption.APPEND
);
} catch (IOException e) {
throw new RuntimeException(e);
}