C# Tips | ファイル・ディレクトリ操作:一時フォルダ作成

C sharp C#
スポンサーリンク

はじめに 一時フォルダは「作業用の安全な砂場」

一時ファイルと同じくらい、業務でよく使うのが「一時フォルダ」です。
大きな 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 でランダムなフォルダを作る」
という動きをしていることです。

二つ目は、DisposeDirectory.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 で囲む。

ここまで押さえておけば、「一時フォルダがゴミだらけ」「本番フォルダが中間ファイルで汚れる」といった悩みはかなり減ります。

タイトルとURLをコピーしました