4日目のゴール
4日目のテーマは
「ファイルを“読みっぱなし・書きっぱなし”から、“更新できるデータ”として扱う」 ことです。
1〜3日目であなたは、
ファイルに文字を書いて永続化する
追記モードで履歴を溜める
1行=1レコードとして構造を持たせる(ID|日付|本文)
というところまで来ました。
4日目では一歩進んで、
「特定のIDのメモだけ削除する」
「特定のIDのメモだけ編集する」
という、「更新」の感覚をつかみに行きます。
ここで大事なのは、
ファイルは「途中だけ書き換える」が苦手
だから「読み込んで、作り直す」という発想を持つ
という考え方です。
ファイルは「途中だけ書き換える」が苦手、という現実
メモリとファイルの“書き換えやすさ”の違い
配列やリストなら、
「3番目だけ書き換える」は簡単です。
list.set(2, "新しい値");
で終わりです。
でも、テキストファイルは違います。
ファイルの真ん中あたりにある
「3行目だけ」を直接書き換える、というのは
基本的にはやりません(やりにくいし、壊れやすい)。
代わりに、こう考えます。
全部読み込む
必要な行だけ残す・書き換える
新しい内容でファイルを作り直す
つまり、
「部分更新」ではなく「再構築」 という発想です。
「一度全部読む → 新しいファイルを作る」という基本パターン
削除も編集も、
実はやっていることは同じです。
元のファイルを1行ずつ読む
その行をどう扱うか決める
新しいファイルに「残したい行」だけを書き出す
削除なら「そのIDの行だけ書き出さない」
編集なら「そのIDの行だけ書き換えて書き出す」
このパターンを、今日は体に入れていきます。
今日の題材:ID指定で「削除」と「編集」ができるメモアプリ
アプリのイメージ
3日目の「ID+日付+本文」アプリに、
メニューを増やします。
「1: メモを追加」
「2: メモ一覧を表示」
「3: メモを削除」
「4: メモを編集」
「0: 終了」
削除では、
「削除したいID」を入力してもらい、
そのIDの行だけを除いてファイルを作り直します。
編集では、
「編集したいID」と「新しい本文」を入力してもらい、
そのIDの行だけを書き換えてファイルを作り直します。
削除の考え方:そのIDの行だけ“書き出さない”
削除の流れを言葉で整理する
ID 3 のメモを削除したいとします。
今のファイルがこうだとします。
1|2026-06-06|A2|2026-06-07|B3|2026-06-08|C4|2026-06-09|D
やりたいことは、
「3 の行だけ消して、1,2,4 は残す」です。
流れはこうです。
元のファイルを1行ずつ読む
行を split して ID を取り出す
ID が 3 なら、その行は新しいファイルに書かない
それ以外の行は、新しいファイルにそのまま書く
最後に、新しいファイルで元のファイルを置き換える
この「書き出さない」というのが削除の本質です。
削除のコード(シンプル版)
private static void deleteMemo(Scanner scanner) {
System.out.print("削除したいメモのIDを入力してください: ");
String idStr = scanner.nextLine();
if (idStr.isEmpty()) {
System.out.println("ID が入力されていません。");
return;
}
int targetId;
try {
targetId = Integer.parseInt(idStr);
} catch (NumberFormatException e) {
System.out.println("ID は整数で入力してください。");
return;
}
String tempFileName = "memo_temp.txt";
boolean deleted = false;
try (BufferedReader reader = new BufferedReader(new FileReader(FILE_NAME));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFileName))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split("\\|", 3);
if (parts.length >= 1) {
try {
int id = Integer.parseInt(parts[0]);
if (id == targetId) {
deleted = true;
continue;
}
} catch (NumberFormatException e) {
// ID が数字でない行は、そのまま残す
}
}
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
System.out.println("削除処理中にエラーが発生しました。");
System.out.println("(開発者向け情報)" + e.getMessage());
return;
}
if (!deleted) {
System.out.println("指定されたIDのメモが見つかりませんでした。");
new java.io.File(tempFileName).delete();
return;
}
java.io.File original = new java.io.File(FILE_NAME);
java.io.File temp = new java.io.File(tempFileName);
if (original.delete() && temp.renameTo(original)) {
System.out.println("ID " + targetId + " のメモを削除しました。");
} else {
System.out.println("ファイルの置き換えに失敗しました。");
}
}
Javaここでの重要ポイントを、丁寧に見ていきます。
一時ファイルを使う理由と流れ
なぜ「一時ファイル」を使うのか
直接 memo.txt を書き換えるのではなく、memo_temp.txt という一時ファイルを使っています。
理由はシンプルです。
元のファイルを読みながら
同じファイルに書き込むと
中身がぐちゃぐちゃになりやすい
だから、
元のファイルは「読み専用」にする
新しい内容は「別ファイル」に書く
最後に「新しいファイルで元のファイルを置き換える」
という安全な手順を踏みます。
一時ファイルを使った更新の3ステップ
削除も編集も、基本はこの3ステップです。
元ファイルを読みながら、一時ファイルに「新しい内容」を書く
処理が成功したら、元ファイルを削除する
一時ファイルの名前を、元ファイルの名前に変える
コードでは、ここにあたります。
java.io.File original = new java.io.File(FILE_NAME);
java.io.File temp = new java.io.File(tempFileName);
if (original.delete() && temp.renameTo(original)) {
// 成功
} else {
// 失敗
}
Javaこの流れを覚えておくと、
「ファイルの更新」は怖くなくなります。
編集の考え方:そのIDの行だけ“書き換えて書き出す”
編集の流れを言葉で整理する
ID 3 のメモを「新しい本文」に変えたいとします。
今のファイルがこうだとします。
1|2026-06-06|A2|2026-06-07|B3|2026-06-08|C4|2026-06-09|D
やりたいことは、
「3 の行だけ本文を変えて、他はそのまま」です。
流れはこうです。
元のファイルを1行ずつ読む
行を split して ID を取り出す
ID が 3 なら、「新しい本文」を使って行を組み立て直す
それ以外の行は、そのまま書き出す
最後に、一時ファイルで元のファイルを置き換える
削除との違いは、
削除 → 「その行を書き出さない」
編集 → 「その行を書き換えて書き出す」
というだけです。
編集のコード(シンプル版)
private static void editMemo(Scanner scanner) {
System.out.print("編集したいメモのIDを入力してください: ");
String idStr = scanner.nextLine();
if (idStr.isEmpty()) {
System.out.println("ID が入力されていません。");
return;
}
int targetId;
try {
targetId = Integer.parseInt(idStr);
} catch (NumberFormatException e) {
System.out.println("ID は整数で入力してください。");
return;
}
System.out.print("新しい本文を入力してください: ");
String newBody = scanner.nextLine();
if (newBody.isEmpty()) {
System.out.println("空の本文には編集しません。");
return;
}
String tempFileName = "memo_temp.txt";
boolean edited = false;
try (BufferedReader reader = new BufferedReader(new FileReader(FILE_NAME));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFileName))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split("\\|", 3);
if (parts.length == 3) {
try {
int id = Integer.parseInt(parts[0]);
String date = parts[1];
String body = parts[2];
if (id == targetId) {
String newLine = id + "|" + date + "|" + newBody;
writer.write(newLine);
writer.newLine();
edited = true;
continue;
}
} catch (NumberFormatException e) {
// ID が数字でない行は、そのまま書き出す
}
}
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
System.out.println("編集処理中にエラーが発生しました。");
System.out.println("(開発者向け情報)" + e.getMessage());
return;
}
if (!edited) {
System.out.println("指定されたIDのメモが見つかりませんでした。");
new java.io.File(tempFileName).delete();
return;
}
java.io.File original = new java.io.File(FILE_NAME);
java.io.File temp = new java.io.File(tempFileName);
if (original.delete() && temp.renameTo(original)) {
System.out.println("ID " + targetId + " のメモを編集しました。");
} else {
System.out.println("ファイルの置き換えに失敗しました。");
}
}
Java4日目版:追加・一覧・削除・編集ができるアプリ全体
全体像をまとめたコード
メニューだけざっくり示します。
中身は、3日目の addMemo と、今日の deleteMemo・editMemo を組み合わせた形です。
public class FileSaveAppDay4 {
private static final String FILE_NAME = "memo.txt";
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println();
System.out.println("=== ファイル保存アプリ 4日目 ===");
System.out.println("1: メモを追加");
System.out.println("2: メモ一覧を表示");
System.out.println("3: メモを削除");
System.out.println("4: メモを編集");
System.out.println("0: 終了");
System.out.print("番号を選んでください: ");
String choice = scanner.nextLine();
if ("0".equals(choice)) {
System.out.println("終了します。");
break;
} else if ("1".equals(choice)) {
addMemo(scanner);
} else if ("2".equals(choice)) {
showAllMemos();
} else if ("3".equals(choice)) {
deleteMemo(scanner);
} else if ("4".equals(choice)) {
editMemo(scanner);
} else {
System.out.println("不正な入力です。0〜4 のいずれかを入力してください。");
}
}
scanner.close();
}
// addMemo, showAllMemos, deleteMemo, editMemo はここまで説明したもの
}
Javaここまで来ると、
ファイルはもう「ただの保存場所」ではなく、
「追加・一覧・削除・編集ができる、小さなデータストア」
として扱えるようになっています。
4日目で“体に入れてほしい感覚”
ファイル更新は「部分書き換え」ではなく「再構築」
今日いちばん大事なのは、
「ファイルの更新=一度全部読んで、新しく作り直す」
という感覚です。
削除 → その行だけ書き出さない
編集 → その行だけ書き換えて書き出す
どちらも、
元ファイルを読みながら
一時ファイルに「新しい姿」を書いていく
最後に一時ファイルで元ファイルを置き換える
という同じパターンで実現できます。
このパターンを覚えておくと、
ToDo アプリでも、家計簿でも、
「特定の行だけ削除・編集したい」という要求に
落ち着いて応えられるようになります。
永続化は「データのライフサイクルを設計する」こと
3日目までで、
「どう保存するか」「どう読むか」を考えました。
4日目では、
「どう更新するか」「どう消すか」まで踏み込みました。
追加 → 一番下に追記
一覧 → 全行を読み込んで表示
削除 → その行を除いて再構築
編集 → その行を書き換えて再構築
ここまで考えられるようになると、
永続化はもう「ただのファイル操作」ではなく、
「データの一生(ライフサイクル)を設計すること」
として見えてきます。
その視点を持てている時点で、
あなたはもう、かなり“アプリ開発者の目線”に近づいています。

