Java Arena
Step 2 of 5

Adding to a file

Writing replaces

A workout log gets a new line after every workout. Here's workouts.txt after two of them, and a program that should add Friday's yoga to it, written with what step 1 taught. It then reads the file back:

The file workouts.txt
Mon: run, 5 km
Wed: swim, 40 min
import java.io.PrintWriter;
import java.nio.file.Paths;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        PrintWriter writer = new PrintWriter("workouts.txt");
        writer.println("Fri: yoga, 30 min");
        writer.close();

        try (Scanner reader = new Scanner(Paths.get("workouts.txt"))) {
            while (reader.hasNextLine()) {
                System.out.println(reader.nextLine());
            }
        }
    }
}
Output
Fri: yoga, 30 min

Monday's run and Wednesday's swim are gone: creating the PrintWriter emptied the file before anything was written. That's right for a file the program writes from scratch, but a log should grow.

FileWriter, which can append

FileWriter, also in java.io, writes into a file as well, and its constructor takes a second parameter: new FileWriter("workouts.txt", true). true means append: the file keeps what it holds, and the new text goes after it. When the file doesn't exist yet, it's created, as before.

A FileWriter has no print or println. Its write methods write the text as it is, with no line break: write("Fri: yoga, 30 min\n") needs the \n at the end. Give the FileWriter to a PrintWriter's constructor instead, and you get println and print, which write through the FileWriter into the file:

The file workouts.txt
Mon: run, 5 km
Wed: swim, 40 min
import java.io.FileWriter;
import java.io.PrintWriter;
import java.nio.file.Paths;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        PrintWriter writer = new PrintWriter(new FileWriter("workouts.txt", true));
        writer.println("Fri: yoga, 30 min");
        writer.close();

        try (Scanner reader = new Scanner(Paths.get("workouts.txt"))) {
            while (reader.hasNextLine()) {
                System.out.println(reader.nextLine());
            }
        }
    }
}
Output
Mon: run, 5 km
Wed: swim, 40 min
Fri: yoga, 30 min
  • new PrintWriter(new FileWriter("workouts.txt", true)) makes two objects. The FileWriter opens the file for appending, and the PrintWriter writes into the FileWriter. Closing the PrintWriter closes the FileWriter too.
  • Without the true, or with false, a FileWriter empties the file first, just as a PrintWriter does.
  • FileWriter's constructor can throw an IOException (step 1's FileNotFoundException is one kind of it), so it needs throws or catch too. A catch (IOException e) block, with import java.io.IOException;, catches every kind.
  • Every run adds one line. Run the program three times on your own computer, and the file ends with three yoga lines. Each check on Java Arena starts again from the files the test gives, so there each run adds exactly one.

Append or replace?

  • A log, a diary or a list of events grows: each run adds to it, so the program appends.
  • A file that holds all of a program's data, such as a to-do list or a high-score table, is written again from the start each time, so it's replaced. Appending there would write the old contents into the file a second time. Step 4 is about such files.

Your task

Challenge 1 of 3

A reading log. The program reads the title of a book you've just finished, adds it as a new line at the end of books.txt, and prints Added: and the title. Fill in the blanks, so that the titles already in the file stay, and the file is created if there isn't one yet. For the input Dune and the file shown below, it prints:

Added: Dune

and books.txt then ends with the line Dune.

Challenge 2

A calculator keeps its history in history.txt, and its method save writes a line there, appending or not. The folder is empty when the program starts. What does the program print?

Challenge 3

A sleep tracker adds a line to its log every morning. Write the method logNight(String fileName, String day, int hours), which adds the line day: hours h, such as Tue: 7 h, at the end of the file, keeping what the file holds. When there's no such file yet, it's created. Use a FileWriter that appends.

Nobody sleeps less than 0 or more than 24 hours in a night. For such hours, logNight throws an IllegalArgumentException with the message impossible: and the hours and hours, such as impossible: 30 hours, and writes nothing.

The check calls logNight for Tuesday (7 hours) and Wednesday (6 hours) on the file shown below, which has Monday's line, and after it sleep.txt should hold:

Mon: 8 h
Tue: 7 h
Wed: 6 h