はじめに
Java実践編では、実際の開発で必要になるスキルを学びます。第1回はファイル操作です。
Java 7以降はjava.nio.fileパッケージの使用が推奨されています。
テキストファイルの読み書き
ファイルを読む
import java.nio.file.*;
import java.io.*;
import java.util.*;
import java.nio.charset.StandardCharsets;
public class FileReadExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("sample.txt");
// ファイル全体を読み込む
String content = Files.readString(path, StandardCharsets.UTF_8);
System.out.println(content);
// 全行をリストとして取得
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
for (String line : lines) {
System.out.println(line);
}
// 1行ずつストリームで処理(大容量ファイル向け)
try (var stream = Files.lines(path, StandardCharsets.UTF_8)) {
stream.forEach(System.out::println);
}
}
}
ファイルに書き込む
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class FileWriteExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("output.txt");
// 新規作成・上書き
Files.writeString(path, "こんにちは\nJava\n", StandardCharsets.UTF_8);
// 追記
Files.writeString(path, "追加の行\n",
StandardCharsets.UTF_8,
StandardOpenOption.APPEND);
// 複数行を書き込み
List<String> lines = List.of("1行目", "2行目", "3行目");
Files.write(path, lines, StandardCharsets.UTF_8);
// オプション指定
Files.write(path, lines,
StandardCharsets.UTF_8,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING);
}
}
try-with-resourcesによるリソース管理
ファイルは自動的に閉じられます。
import java.io.*;
import java.nio.charset.StandardCharsets;
public class TryWithResourcesExample {
public static void main(String[] args) {
// 良い例(自動でclose)
try (BufferedReader reader = new BufferedReader(
new FileReader("file.txt", StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// ここでreaderは自動的に閉じられる
// 複数リソースも可能
try (
var reader = new BufferedReader(new FileReader("input.txt"));
var writer = new BufferedWriter(new FileWriter("output.txt"))
) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
StandardOpenOption一覧
| オプション | 説明 |
|---|---|
READ | 読み込みモード |
WRITE | 書き込みモード |
APPEND | 追記 |
CREATE | ファイルがなければ作成 |
CREATE_NEW | 新規作成(既存ならエラー) |
TRUNCATE_EXISTING | 既存ファイルを空にする |
DELETE_ON_CLOSE | クローズ時に削除 |
BufferedReader/BufferedWriter
大容量ファイルの処理にはバッファリングが効果的です。
import java.io.*;
import java.nio.charset.StandardCharsets;
public class BufferedExample {
public static void readLargeFile(String path) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(
Path.of(path), StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
// 1行ずつ処理
processLine(line);
}
}
}
public static void writeLargeFile(String path, List<String> data)
throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(
Path.of(path), StandardCharsets.UTF_8)) {
for (String line : data) {
writer.write(line);
writer.newLine();
}
}
}
}
JSONファイルの操作
Jacksonライブラリを使用します。
<!-- pom.xml -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.util.*;
public class JsonExample {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
// JSONを読み込む
User user = mapper.readValue(new File("user.json"), User.class);
System.out.println(user.getName());
// JSONに書き込む
User newUser = new User("太郎", 25, List.of("Java", "Spring"));
mapper.writerWithDefaultPrettyPrinter()
.writeValue(new File("output.json"), newUser);
// 文字列との変換
String json = mapper.writeValueAsString(newUser);
User parsed = mapper.readValue(json, User.class);
}
}
class User {
private String name;
private int age;
private List<String> skills;
// コンストラクタ、getter、setter
public User() {}
public User(String name, int age, List<String> skills) {
this.name = name;
this.age = age;
this.skills = skills;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public List<String> getSkills() { return skills; }
public void setSkills(List<String> skills) { this.skills = skills; }
}
CSVファイルの操作
シンプルなCSV処理の例です。
import java.nio.file.*;
import java.util.*;
import java.nio.charset.StandardCharsets;
public class CsvExample {
public static List<Map<String, String>> readCsv(String path)
throws IOException {
List<String> lines = Files.readAllLines(
Path.of(path), StandardCharsets.UTF_8);
if (lines.isEmpty()) return List.of();
String[] headers = lines.get(0).split(",");
List<Map<String, String>> result = new ArrayList<>();
for (int i = 1; i < lines.size(); i++) {
String[] values = lines.get(i).split(",");
Map<String, String> row = new HashMap<>();
for (int j = 0; j < headers.length; j++) {
row.put(headers[j], j < values.length ? values[j] : "");
}
result.add(row);
}
return result;
}
public static void writeCsv(String path, List<Map<String, String>> data)
throws IOException {
if (data.isEmpty()) return;
List<String> headers = new ArrayList<>(data.get(0).keySet());
List<String> lines = new ArrayList<>();
lines.add(String.join(",", headers));
for (Map<String, String> row : data) {
List<String> values = new ArrayList<>();
for (String header : headers) {
values.add(row.getOrDefault(header, ""));
}
lines.add(String.join(",", values));
}
Files.write(Path.of(path), lines, StandardCharsets.UTF_8);
}
}
パス操作
import java.nio.file.*;
public class PathExample {
public static void main(String[] args) {
// パスの作成
Path path = Path.of("documents", "report.txt");
System.out.println(path); // documents/report.txt
// パス情報の取得
Path filePath = Path.of("/home/user/documents/report.txt");
System.out.println(filePath.getFileName()); // report.txt
System.out.println(filePath.getParent()); // /home/user/documents
System.out.println(filePath.getRoot()); // /
System.out.println(filePath.getNameCount()); // 4
// 絶対パスに変換
Path absolute = Path.of("file.txt").toAbsolutePath();
System.out.println(absolute);
// パスの結合
Path base = Path.of("/home/user");
Path resolved = base.resolve("documents/file.txt");
System.out.println(resolved); // /home/user/documents/file.txt
// パスの正規化
Path normalized = Path.of("/foo/bar/../baz").normalize();
System.out.println(normalized); // /foo/baz
}
}
ディレクトリ操作
import java.nio.file.*;
import java.io.IOException;
public class DirectoryExample {
public static void main(String[] args) throws IOException {
Path path = Path.of("sample.txt");
// 存在確認
System.out.println(Files.exists(path));
System.out.println(Files.isRegularFile(path));
System.out.println(Files.isDirectory(path));
// ファイルサイズ
System.out.println(Files.size(path));
// ディレクトリ作成
Files.createDirectory(Path.of("new_folder"));
Files.createDirectories(Path.of("a/b/c"));
// ディレクトリ内のファイル一覧
try (var stream = Files.list(Path.of("."))) {
stream.forEach(System.out::println);
}
// 再帰的にファイルを検索
try (var stream = Files.walk(Path.of("."))) {
stream.filter(p -> p.toString().endsWith(".java"))
.forEach(System.out::println);
}
// ファイル削除
Files.delete(Path.of("file.txt"));
Files.deleteIfExists(Path.of("maybe.txt"));
// コピーと移動
Files.copy(Path.of("src.txt"), Path.of("dst.txt"),
StandardCopyOption.REPLACE_EXISTING);
Files.move(Path.of("old.txt"), Path.of("new.txt"),
StandardCopyOption.REPLACE_EXISTING);
}
}
実践例:ログファイル処理
import java.nio.file.*;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.nio.charset.StandardCharsets;
public class LogProcessor {
record ErrorEntry(int line, String content) {}
public static List<ErrorEntry> parseLogFile(String logPath)
throws IOException {
List<ErrorEntry> errors = new ArrayList<>();
int lineNum = 0;
try (BufferedReader reader = Files.newBufferedReader(
Path.of(logPath), StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
lineNum++;
if (line.contains("ERROR")) {
errors.add(new ErrorEntry(lineNum, line.trim()));
}
}
}
return errors;
}
public static void saveErrorReport(
List<ErrorEntry> errors,
String outputPath) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(
Path.of(outputPath), StandardCharsets.UTF_8)) {
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
writer.write("エラーレポート - " + timestamp);
writer.newLine();
writer.write("=".repeat(50));
writer.newLine();
writer.newLine();
for (ErrorEntry error : errors) {
writer.write("行 " + error.line() + ": " + error.content());
writer.newLine();
}
writer.newLine();
writer.write("合計: " + errors.size() + "件のエラー");
writer.newLine();
}
}
public static void main(String[] args) throws IOException {
List<ErrorEntry> errors = parseLogFile("app.log");
saveErrorReport(errors, "error_report.txt");
}
}
まとめ
java.nio.file.Filesでモダンなファイル操作try-with-resourcesで安全なリソース管理StandardCharsets.UTF_8で文字エンコーディング指定- Jacksonライブラリ統合JSONを扱う
Pathでパス操作
次回は例外処理について学びます。