Reading from and writing to a file in Java

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(",");

Regular expressions allow you (among other things) to use more expressive delimiters. Regular expressions will be seen in another course of the bachelor (alternatively, you can look at last year’s course for an introduction).

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 the 22-23 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);
}