Java Java7

Java 7: Files.readAllLines and Files.write

Java 7 Files.readAllLines and Files.write

Java 7: Files.readAllLines and Files.write

Prior to Java 7, reading from and writing to files required a significant amount of boilerplate code. Developers had to manually instantiate FileReader, wrap it in a BufferedReader, iterate through the file line by line using a while loop, and carefully manage exceptions and resource closures using finally blocks. Writing data was equally cumbersome, involving FileWriter and BufferedWriter. This verbosity made simple file I/O operations tedious and prone to resource leak errors.

The introduction of the NIO.2 API in Java 7 revolutionized file handling with the java.nio.file.Files utility class. This class provides static methods that perform common file operations in a single line of code. Two of the most useful methods for text manipulation are Files.readAllLines() and Files.write(). These methods abstract away the underlying streams, readers, and writers, allowing developers to focus directly on the data.

Files.readAllLines(Path path, Charset cs) reads an entire file into memory and returns a List<String>, where each element represents a line in the file. This is incredibly convenient for processing small to medium-sized configuration files or logs. Conversely, Files.write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options) takes a collection of strings and writes them directly to a file, handling file creation or overwriting automatically based on the provided options.

While these methods are powerful and clean, developers must exercise caution when dealing with very large files. Because readAllLines() loads the entire file contents into the application's heap memory at once, it can easily cause an OutOfMemoryError if the file is larger than the available RAM. For massive files, the traditional streaming approach or the newer Files.lines() (introduced in Java 8) is still required.

How it Works

You use the Paths.get() method to define a Path object representing your file. Then, you simply pass this path to Files.readAllLines() to get a List of strings. To write, you pass the path and an Iterable (like a List) of strings to Files.write(). The methods automatically handle opening and closing the file resources.

Java Example

Scenario 1: Writing and Reading a Simple Text File

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.io.IOException;

public class FilesUtilityExample1 {
    public static void main(String[] args) {
        Path filePath = Paths.get("sample_log.txt");
        List<String> linesToWrite = Arrays.asList("Line 1: Application started", "Line 2: Processing data", "Line 3: Application closed");
        
        try {
            // Write lines to file
            Files.write(filePath, linesToWrite, StandardCharsets.UTF_8);
            System.out.println("File written successfully.");
            
            // Read lines from file
            List<String> readLines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
            System.out.println("Reading from file:");
            for (String line : readLines) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Output

File written successfully.
Reading from file:
Line 1: Application started
Line 2: Processing data
Line 3: Application closed

Scenario 2: Appending Data to an Existing File

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.io.IOException;

public class FilesUtilityExample2 {
    public static void main(String[] args) {
        Path filePath = Paths.get("sample_log.txt");
        List<String> moreLines = Arrays.asList("Line 4: System rebooted");
        
        try {
            // Append line using StandardOpenOption.APPEND
            Files.write(filePath, moreLines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
            System.out.println("Data appended successfully.");
            
            // Read to verify
            List<String> allLines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
            System.out.println("Updated File Content:");
            System.out.println(String.join("\n", allLines));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Output

Data appended successfully.
Updated File Content:
Line 1: Application started
Line 2: Processing data
Line 3: Application closed
Line 4: System rebooted

Scenario 3: Handling Missing Files

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
import java.nio.file.NoSuchFileException;

public class FilesUtilityExample3 {
    public static void main(String[] args) {
        Path missingFile = Paths.get("does_not_exist.txt");
        
        try {
            Files.readAllLines(missingFile, StandardCharsets.UTF_8);
        } catch (NoSuchFileException e) {
            System.out.println("Error: The specified file could not be found -> " + e.getFile());
        } catch (IOException e) {
            System.out.println("General I/O Error.");
        }
    }
}

Output

Error: The specified file could not be found -> does_not_exist.txt

Key Points

  • Provides a one-liner approach for reading and writing entire text files.
  • Eliminates boilerplate code for streams and resource management.
  • Returns a convenient List<String> for reading and accepts an Iterable<String> for writing.
  • Not suitable for extremely large files as it loads all content into memory simultaneously.
Topics: Java Java7
← Newer Post Older Post →