はじめに 一時フォルダは「作業用の安全な砂場」
一時ファイルと同じくらい、業務でよく使うのが「一時フォルダ」です。
大きな ZIP を展開して中身を処理するとき、複数ファイルを一時的に並べてからまとめてアップロードするとき、バッチ処理の中間成果物を置いておくときなど、「一時的に複数ファイルを置ける場所」があると、とても設計しやすくなります。
ポイントは、「本番のフォルダを汚さない」「処理が終わったら丸ごと消せる」ということです。
ここでは、C# 初心者向けに「一時フォルダをどう作るか」「どう片付けるか」「どうユーティリティ化するか」を、実務目線で丁寧に解説していきます。
一時フォルダの基本 Path.GetTempPath と Directory.CreateDirectory
OS 標準の一時フォルダを知る Path.GetTempPath
まず、「一時フォルダをどこに作るか」という話からです。
C# では、Path.GetTempPath() を呼ぶと、OS が用意している「一時フォルダ」のパスを取得できます。
using System;
using System.IO;
class Program
{
static void Main()
{
string tempRoot = Path.GetTempPath();
Console.WriteLine("OS の一時フォルダ: " + tempRoot);
}
}
C#Windows なら、だいたいC:\Users\ユーザー名\AppData\Local\Temp\
のような場所が返ってきます。
一時フォルダを作るときは、基本的にこの配下に作るのがセオリーです。
自分で C:\temp などを勝手に決めるより、OS 標準の場所を使ったほうが、クリーンアップの対象になりやすく、権限周りでも安全です。
一時フォルダを作る Directory.CreateDirectory
実際にフォルダを作るのは、Directory.CreateDirectory です。
using System;
using System.IO;
class Program
{
static void Main()
{
string tempRoot = Path.GetTempPath();
string tempDir = Path.Combine(tempRoot, "MyAppTemp");
Directory.CreateDirectory(tempDir);
Console.WriteLine("一時フォルダを作成しました: " + tempDir);
}
}
C#Directory.CreateDirectory は、指定したフォルダが存在しなければ作成し、すでに存在していれば何もしません。
つまり、「とりあえずこのパスをフォルダとして用意しておきたい」というときに、そのまま呼んで問題ありません。
ここまでで、「OS の一時フォルダの場所を知る」「その配下に自分用の一時フォルダを作る」という基本が押さえられます。
ランダムな一時フォルダを作る Path.GetRandomFileName
名前がかぶらない一時フォルダを作りたい
複数の処理が同時に動く可能性がある場合、「毎回同じフォルダ名」だと中身がぶつかります。
そこで、「毎回ランダムな名前の一時フォルダを作る」というパターンがよく使われます。
ここで役に立つのが Path.GetRandomFileName() です。
これは「衝突しにくいランダムなファイル名(文字列)を返す」メソッドで、フォルダ名としても使えます。
using System;
using System.IO;
class Program
{
static void Main()
{
string tempRoot = Path.GetTempPath();
string folderName = Path.GetRandomFileName();
string tempDir = Path.Combine(tempRoot, folderName);
Directory.CreateDirectory(tempDir);
Console.WriteLine("ランダム一時フォルダ: " + tempDir);
}
}
C#このようにしておけば、同じプログラムが同時に複数動いても、
それぞれ別々の一時フォルダを使うことができます。
実務で使える「一時フォルダ」ユーティリティクラス
使い終わったら自動で消える TempDirectory
一時フォルダは「作りっぱなし」にしてはいけません。
処理が終わったら、中身ごとフォルダを削除するのが基本です。
毎回 try-finally で削除を書くのは面倒なので、IDisposable を実装した「使い捨て一時フォルダ」クラスを作ると、とても扱いやすくなります。
using System;
using System.IO;
public sealed class TempDirectory : IDisposable
{
public string Path { get; }
public TempDirectory()
: this(System.IO.Path.Combine(
System.IO.Path.GetTempPath(),
System.IO.Path.GetRandomFileName()))
{
}
public TempDirectory(string directoryPath)
{
if (string.IsNullOrWhiteSpace(directoryPath))
{
throw new ArgumentException("ディレクトリパスが空です。", nameof(directoryPath));
}
Path = directoryPath;
Directory.CreateDirectory(Path);
}
public void Dispose()
{
try
{
if (Directory.Exists(Path))
{
Directory.Delete(Path, recursive: true);
}
}
catch
{
}
}
}
C#ここでの重要ポイントを整理します。
一つ目は、デフォルトコンストラクタで
「GetTempPath 配下に GetRandomFileName でランダムなフォルダを作る」
という動きをしていることです。
二つ目は、Dispose で Directory.Delete(Path, recursive: true) を呼び、
フォルダの中身ごと丸ごと削除していることです。recursive: true を付けることで、配下のファイル・サブフォルダも一括削除されます。
TempDirectory の使い方
使い方はとてもシンプルで、using で囲むだけです。
using System;
using System.IO;
class Program
{
static void Main()
{
using (var tempDir = new TempDirectory())
{
Console.WriteLine("一時フォルダ: " + tempDir.Path);
string file1 = System.IO.Path.Combine(tempDir.Path, "a.txt");
string file2 = System.IO.Path.Combine(tempDir.Path, "b.txt");
File.WriteAllText(file1, "一時データ A");
File.WriteAllText(file2, "一時データ B");
Console.WriteLine("ファイル A: " + file1);
Console.WriteLine("ファイル B: " + file2);
Console.WriteLine("ここで ZIP 圧縮やアップロードなどの処理を行うイメージです。");
}
Console.WriteLine("using を抜けた時点で一時フォルダは中身ごと削除済みです。");
}
}
C#呼び出し側は「一時フォルダの寿命=using ブロックの範囲」として扱えるので、
削除漏れを心配しなくて済みます。
一時フォルダを使う典型的な業務シナリオ
ZIP 展開 → 処理 → 後片付け
よくあるパターンとして、「ZIP ファイルを一時フォルダに展開して、中身を処理する」という流れがあります。
疑似コードで書くと、こんなイメージです。
using (var tempDir = new TempDirectory())
{
string extractPath = tempDir.Path;
// ZIP を一時フォルダに展開
System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);
// 展開されたファイルを処理
foreach (string file in Directory.GetFiles(extractPath, "*.*", SearchOption.AllDirectories))
{
Console.WriteLine("処理対象: " + file);
// ここでファイル内容を読み込んだり、別の場所にコピーしたりする
}
// using を抜けると、一時フォルダごと全部削除される
}
C#本番のデータフォルダを汚さずに済むうえ、
処理が終わったら一時フォルダごと消えるので、後片付けもシンプルです。
大量ファイルの一時退避
別の例として、「本番フォルダのファイルを一時フォルダに退避してから、順次処理する」というパターンもあります。
using (var tempDir = new TempDirectory())
{
string backupDir = tempDir.Path;
foreach (string file in Directory.GetFiles(sourceDir))
{
string dest = System.IO.Path.Combine(backupDir, System.IO.Path.GetFileName(file));
File.Copy(file, dest);
}
// backupDir 内のファイルを使って安全に処理
// 問題がなければ本番側を更新、問題があれば何もしない
} // ここで backupDir ごと削除
C#「一時フォルダにコピーしてから処理する」ことで、
途中で失敗しても本番データを壊さない、という設計ができます。
一時フォルダ利用時の注意点と考え方
削除漏れとディスク圧迫
一時フォルダを作るだけ作って削除しないと、
OS の Temp 配下がどんどんゴミだらけになり、ディスクを圧迫します。
だからこそ、「一時フォルダは必ずどこかで消す」というルールを徹底する必要があります。TempDirectory のように IDisposable に閉じ込めてしまうのは、そのための強力なパターンです。
例外が出ても確実に消す
using を使えば、ブロック内で例外が発生しても Dispose は必ず呼ばれます。
つまり、「処理が成功しても失敗しても、一時フォルダは消える」という状態を作れます。
一時フォルダを手動で管理する場合は、必ず try-finally で削除を書くようにしてください。
string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDir);
try
{
// 一時フォルダを使った処理
}
finally
{
if (Directory.Exists(tempDir))
{
Directory.Delete(tempDir, recursive: true);
}
}
C#まとめ 実務で使える「一時フォルダ作成」ユーティリティの考え方
一時フォルダは、「本番を汚さず、安全に作業するための箱」です。
C# では、次の流れを押さえておくと、実務でとても使いやすくなります。
Path.GetTempPath で OS 標準の一時フォルダの場所を知る。
Path.GetRandomFileName と Directory.CreateDirectory を組み合わせて、衝突しにくい一時フォルダを作る。
TempDirectory のような IDisposable クラスで、「作る→使う→中身ごと削除」を一つのライフサイクルとして閉じ込める。
ZIP 展開や大量ファイル処理など、「一時的にファイルを広げる」処理は、必ず一時フォルダを経由させる設計にする。
例外が出ても確実に削除されるように、using または try-finally で囲む。
ここまで押さえておけば、「一時フォルダがゴミだらけ」「本番フォルダが中間ファイルで汚れる」といった悩みはかなり減ります。
