一時ファイル作成は「一時的な作業領域を安全に借りる」技
業務システムでは、「大きなデータを一度ファイルに落としてから処理したい」「ZIP を展開して中身を検査したい」「外部システムに渡す前に一時的にファイルを組み立てたい」といった、“一時的な作業領域”が必要な場面がよくあります。
このときに便利なのが「一時ファイル」です。
一時ファイルを正しく扱えると、メモリを無駄に使わずに済み、障害調査のときに中身を確認しやすくなります。
逆に、適当に作って消し忘れると、ディスクを食いつぶしたり、機密情報を残しっぱなしにしたりと、実務ではかなり危険です。
だからこそ、「一時ファイル作成ユーティリティ」をきちんと設計しておく価値があります。
基本:Files.createTempFile で一時ファイルを作る
最小のサンプルで動きをつかむ
Java 7 以降では、java.nio.file.Files の createTempFile を使うのが基本です。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class TempFileBasic {
public static void main(String[] args) throws IOException {
Path temp = Files.createTempFile("myapp-", ".tmp");
System.out.println("一時ファイル: " + temp);
}
}
Java第一引数がプレフィックス(ファイル名の先頭)、第二引数がサフィックス(拡張子)です。
実際のファイル名は OS が一意になるように決めてくれるので、myapp-1234567890.tmp のような名前になります。
保存場所は、OS が用意している「一時ディレクトリ」です。
Windows なら C:\Users\...\AppData\Local\Temp、Linux なら /tmp など、環境によって異なりますが、createTempFile がよしなに選んでくれます。
ここでの重要ポイントは、「自分で“かぶらないファイル名”を考えなくてよい」ことです。
マルチスレッドや複数プロセスが同時に動いていても、createTempFile は衝突しないように名前を付けてくれます。
一時ファイルの「作る」と「消す」をセットで考える
作るのは簡単、難しいのは「いつ・どう消すか」
一時ファイルで一番大事なのは、「作り方」よりも「消し方」です。
作るだけ作って消し忘れると、時間とともに一時ディレクトリがゴミだらけになり、ディスクフルの原因になります。
まずは、典型的な「作って、使って、消す」流れを見てみましょう。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class TempFileUseAndDelete {
public static void main(String[] args) throws IOException {
Path temp = Files.createTempFile("myapp-", ".csv");
try {
// 一時ファイルに何か書く
Files.writeString(temp, "id,name\n1,foo\n2,bar\n");
// ここで外部システムに渡したり、別処理で読んだりする
String content = Files.readString(temp);
System.out.println(content);
} finally {
// 使い終わったら削除
Files.deleteIfExists(temp);
}
}
}
Javaここで深掘りしたいのは、「try-finally で“必ず消す”を保証する」という発想です。
途中で例外が起きても、finally ブロックは必ず実行されるので、「処理が失敗したけど一時ファイルだけ残り続ける」という状態を減らせます。
deleteOnExit に頼りすぎない
File クラスには deleteOnExit() というメソッドがあり、「JVM 終了時に削除してね」とお願いできます。
Path temp = Files.createTempFile("myapp-", ".tmp");
temp.toFile().deleteOnExit();
Javaただし、これは「プロセスが正常終了したとき」にしか効きません。
強制終了されたり、プロセスが長時間動き続けるサーバーアプリだったりすると、一時ファイルが溜まり続けることになります。
実務では、「基本は使い終わったら自分で消す」「どうしても消し忘れが怖いところだけ補助的に deleteOnExit を使う」くらいの距離感が健全です。
実務で使える「一時ファイル作成ユーティリティ」の最小形
プレフィックス・拡張子・削除責務をまとめる
毎回 createTempFile を直接呼ぶのではなく、「アプリ用の一時ファイル」を作るユーティリティを用意しておくと便利です。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public final class TempFiles {
private TempFiles() {}
public static Path create(String suffix) throws IOException {
return Files.createTempFile("myapp-", suffix);
}
public static Path createCsv() throws IOException {
return create(".csv");
}
public static void safeDelete(Path path) {
try {
Files.deleteIfExists(path);
} catch (IOException e) {
// ログにだけ出して、アプリの処理は続行するなど
System.err.println("一時ファイルの削除に失敗しました: " + path + " : " + e.getMessage());
}
}
}
Java使う側はこう書けます。
Path temp = TempFiles.createCsv();
try {
// 何かに使う
} finally {
TempFiles.safeDelete(temp);
}
Javaここでの重要ポイントは、「“どんな名前でどこに作るか”と“削除時の扱い”を一箇所に集約している」ことです。
プレフィックスを変えたくなったり、削除失敗時のログ出力を変えたくなったりしても、TempFiles だけ直せば済みます。
例題:大きな ZIP を一時ファイルに落としてから展開する
メモリに乗せずに一時ファイルで受ける
例えば、「HTTP で大きな ZIP ファイルをダウンロードして、中身を展開する」という処理を考えます。
これを全部メモリに乗せると、簡単に OutOfMemoryError になります。
そこで、一度一時ファイルに落としてから処理するパターンがよく使われます。
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.ZipInputStream;
public class ZipDownloadJob {
public void run(InputStream httpBody) throws IOException {
Path tempZip = TempFiles.create(".zip");
try {
// HTTP のボディを一時ファイルに書き出す
Files.copy(httpBody, tempZip);
// 一時ファイルから ZIP を展開する
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(tempZip))) {
// エントリごとの処理…
}
} finally {
TempFiles.safeDelete(tempZip);
}
}
}
Javaここで深掘りしたいのは、「一時ファイルを使うことで“メモリ使用量”と“処理の見通し”を両方よくしている」点です。
ストリームをそのまま展開することもできますが、「途中で中身を確認したい」「障害時にファイルを残して調査したい」といった実務的なニーズを考えると、
一時ファイルに落とす設計はかなり現場向きです。
一時ディレクトリを指定して作るパターン
デフォルトではなく「アプリ専用の一時ディレクトリ」を使う
createTempFile には、「どのディレクトリに作るか」を指定できるオーバーロードもあります。
Path baseDir = Path.of("work/tmp");
Files.createDirectories(baseDir);
Path temp = Files.createTempFile(baseDir, "myapp-", ".tmp");
Javaこうすると、OS の共通一時ディレクトリではなく、「アプリ専用の一時ディレクトリ」にファイルをまとめられます。
実務的なメリットは二つあります。
一つは、「掃除しやすい」ことです。work/tmp 配下だけを定期的に削除するバッチを組めば、「このアプリが残した一時ファイル」だけを安全に消せます。
もう一つは、「他アプリと混ざらない」ことです。
共通の /tmp にいろいろなアプリが一時ファイルを置くと、どれが誰のものか分からなくなります。
専用ディレクトリを切っておけば、「この中はうちのアプリの領域」と割り切れます。
これもユーティリティにしておくと便利です。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public final class AppTempFiles {
private static final Path BASE_DIR = Path.of("work/tmp");
private AppTempFiles() {}
public static Path create(String suffix) throws IOException {
Files.createDirectories(BASE_DIR);
return Files.createTempFile(BASE_DIR, "myapp-", suffix);
}
}
Java一時ファイルとセキュリティの視点
機密情報を一時ファイルに書くときの注意
一時ファイルには、個人情報やトークン、パスワードなど、機密性の高いデータが含まれることがあります。
その場合、「消し忘れ」は単なるディスク問題ではなく、情報漏えいリスクになります。
最低限意識しておきたいのは次の二つです。
一つは、「本当に一時ファイルに書く必要があるか」です。
メモリ上だけで完結できるなら、そのほうが痕跡は残りません。
もう一つは、「消すときは確実に消す設計にする」ことです。
try-finally で削除を保証する、エラー時にも削除を試みる、調査のために残す場合はログに明示的に出す、など、
「残す/残さない」を意識的に選ぶようにすると、後から困りにくくなります。
まとめ:一時ファイル作成ユーティリティで身につけるべき感覚
一時ファイル作成は、「とりあえず tmp に吐く」ではなく、「どこに、どんな名前で、いつまで置き、どう消すか」を設計する行為です。
押さえておきたい感覚はこうです。
一時ファイルは Files.createTempFile で作り、自分でユニークな名前を考えない。
作るだけでなく、「try-finally で必ず削除する」流れをセットで書く。
プレフィックス・拡張子・削除ポリシーをユーティリティに集約し、アプリ全体で一貫した扱いにする。
大きなデータや ZIP などは、一時ファイルを使うことでメモリを節約しつつ、調査しやすい形にする。
必要に応じて「アプリ専用の一時ディレクトリ」を用意し、掃除や管理をしやすくする。
