Day 20: File I/O
Java NIO (New I/O)‘s Files and Path classes make file I/O simple and safe. They are more modern than the legacy java.io package, and the code is much more concise.
Path and Files Basics
Working with file paths and performing basic file operations.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathBasic {
public static void main(String[] args) throws IOException {
// Create a Path
Path currentDir = Path.of(".");
Path filePath = Path.of("test.txt");
Path absolutePath = filePath.toAbsolutePath();
System.out.println("Current directory: " + currentDir.toAbsolutePath());
System.out.println("File path: " + absolutePath);
System.out.println("File name: " + filePath.getFileName());
System.out.println("Parent path: " + absolutePath.getParent());
// Check file existence
System.out.println("Exists? " + Files.exists(filePath));
// Create and write a file
Path newFile = Path.of("hello.txt");
Files.writeString(newFile, "Hello, Java File I/O!\nHave a great day!");
System.out.println("File created: " + Files.exists(newFile));
// File information
System.out.println("Size: " + Files.size(newFile) + " bytes");
System.out.println("Readable? " + Files.isReadable(newFile));
System.out.println("Writable? " + Files.isWritable(newFile));
// Cleanup
Files.deleteIfExists(newFile);
}
}
Reading Files
Various ways to read file contents.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
public class FileReadExample {
public static void main(String[] args) throws IOException {
// Create a test file
Path path = Path.of("sample.txt");
String content = """
This is the first line.
This is the second line.
This is the third line.
Let's learn Java file I/O.
This is the last line.
""";
Files.writeString(path, content, StandardCharsets.UTF_8);
// Method 1: Read entire file as a string
String allContent = Files.readString(path);
System.out.println("=== Read all ===");
System.out.println(allContent);
// Method 2: Read as a list of lines
List<String> lines = Files.readAllLines(path);
System.out.println("=== Line by line ===");
for (int i = 0; i < lines.size(); i++) {
System.out.println((i + 1) + ": " + lines.get(i));
}
// Method 3: Read as Stream (suitable for large files)
System.out.println("=== Stream reading ===");
try (Stream<String> lineStream = Files.lines(path)) {
lineStream
.filter(line -> !line.isBlank())
.map(String::trim)
.forEach(System.out::println);
}
// Method 4: Read as bytes
byte[] bytes = Files.readAllBytes(path);
System.out.println("Byte size: " + bytes.length);
// Cleanup
Files.deleteIfExists(path);
}
}
Writing Files
Various ways to write data to files.
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.List;
public class FileWriteExample {
public static void main(String[] args) throws IOException {
// Method 1: Write a string at once
Path path1 = Path.of("output1.txt");
Files.writeString(path1, "Writing in one go\nSecond line");
System.out.println("output1.txt created");
// Method 2: Write a list of lines
Path path2 = Path.of("output2.txt");
List<String> lines = List.of(
"Name: Alice",
"Age: 25",
"Occupation: Developer",
"Language: Java"
);
Files.write(path2, lines, StandardCharsets.UTF_8);
System.out.println("output2.txt created");
// Method 3: Append to existing file (APPEND)
Files.writeString(path1, "\nAppended content!",
StandardOpenOption.APPEND);
System.out.println("Content appended to output1.txt");
// Method 4: Using BufferedWriter (for large files)
Path path3 = Path.of("output3.txt");
try (BufferedWriter writer = Files.newBufferedWriter(path3)) {
for (int i = 1; i <= 100; i++) {
writer.write("Line number " + i);
writer.newLine();
}
}
System.out.println("output3.txt created (" + Files.size(path3) + " bytes)");
// Verify output then cleanup
System.out.println("\n=== output1.txt contents ===");
System.out.println(Files.readString(path1));
Files.deleteIfExists(path1);
Files.deleteIfExists(path2);
Files.deleteIfExists(path3);
}
}
Directory Operations and File Traversal
Creating directories, copying/moving files, and exploring directory contents.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;
public class DirectoryExample {
public static void main(String[] args) throws IOException {
// Create directories
Path dir = Path.of("test-dir");
Path subDir = Path.of("test-dir", "sub", "deep");
Files.createDirectories(subDir); // Auto-creates intermediate paths
System.out.println("Directory created: " + subDir);
// Create files
Path file1 = dir.resolve("file1.txt");
Path file2 = dir.resolve("file2.java");
Path file3 = subDir.resolve("file3.txt");
Files.writeString(file1, "File 1 content");
Files.writeString(file2, "public class Test {}");
Files.writeString(file3, "Nested file");
// Copy a file
Path copied = dir.resolve("file1_copy.txt");
Files.copy(file1, copied, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Copied: " + copied);
// List directory contents (1 level only)
System.out.println("\n=== Directory contents ===");
try (Stream<Path> entries = Files.list(dir)) {
entries.forEach(path -> {
String type = Files.isDirectory(path) ? "[DIR]" : "[FILE]";
System.out.println(type + " " + path.getFileName());
});
}
// Recursive file traversal (all subdirectories)
System.out.println("\n=== Full tree ===");
try (Stream<Path> walk = Files.walk(dir)) {
walk.forEach(path -> {
int depth = dir.relativize(path).getNameCount();
String indent = " ".repeat(depth);
System.out.println(indent + path.getFileName());
});
}
// Find files with a specific extension
System.out.println("\n=== .txt files only ===");
try (Stream<Path> found = Files.find(dir, 10,
(path, attrs) -> path.toString().endsWith(".txt") && attrs.isRegularFile())) {
found.forEach(System.out::println);
}
// Cleanup: delete in reverse order (files first, directories last)
try (Stream<Path> walk = Files.walk(dir)) {
walk.sorted((a, b) -> b.compareTo(a))
.forEach(path -> {
try { Files.deleteIfExists(path); }
catch (IOException ignored) {}
});
}
System.out.println("\nCleanup complete");
}
}
Today’s Exercises
-
CSV Parser: Write a program that reads a CSV file, parses each row, and calculates the sum/average of a specific column. (Create the CSV file programmatically first)
-
Log Analyzer: Read a log file using Stream, filter only ERROR-level logs, and aggregate the error count by time period.
-
File Backup Utility: Write a program that copies all
.txtfiles from a specified directory to abackup/directory with a date suffix. (e.g.,file.txt->backup/file_20260422.txt)