File.Exists() / File.Delete() / File.Copy()
| 対応: | C# 1.0(2002) |
|---|
ファイルの存在を確認する『File.Exists()』、ファイルを削除する『File.Delete()』、ファイルをコピーする『File.Copy()』、ファイルを移動する『File.Move()』の使い方です。
構文
using System.IO; // ファイルが存在するか確認します(true / false を返します)。 bool exists = File.Exists(string path); // ファイルを削除します。存在しない場合は何もしません。 File.Delete(string path); // ファイルをコピーします。 File.Copy(string sourceFileName, string destFileName); // ファイルをコピーします(true で上書き許可)。 File.Copy(string sourceFileName, string destFileName, bool overwrite); // ファイルを移動します(リネームにも使えます)。 File.Move(string sourceFileName, string destFileName); // ファイルを移動します(true で上書き許可、.NET 5 以降)。 File.Move(string sourceFileName, string destFileName, bool overwrite);
メソッド一覧
| メソッド | 概要 |
|---|---|
| File.Exists(path) | 指定したパスのファイルが存在すれば true、存在しなければ false を返します。 |
| File.Delete(path) | 指定したファイルを削除します。ファイルが存在しない場合は例外をスローしません。 |
| File.Copy(src, dest) | src を dest にコピーします。dest が既に存在する場合は IOException をスローします。 |
| File.Copy(src, dest, overwrite) | overwrite を true にすると既存ファイルを上書きします。 |
| File.Move(src, dest) | ファイルを別の場所へ移動します。ファイル名を変えることでリネームにも使えます。 |
| File.GetLastWriteTime(path) | ファイルの最終更新日時を DateTime で返します。 |
サンプルコード
Program.cs
using System;
using System.IO;
string source = "original.txt";
string copyDest = "copy.txt";
string moveDest = "moved.txt";
// テスト用ファイルを作成します。
File.WriteAllText(source, "テスト用のファイルです。");
// File.Exists() でファイルの存在を確認します。
Console.WriteLine(File.Exists(source)); // True
Console.WriteLine(File.Exists("none.txt")); // False
// File.Copy() でファイルをコピーします。
File.Copy(source, copyDest);
Console.WriteLine($"コピー完了: {File.Exists(copyDest)}"); // True
// 上書きコピーには overwrite: true が必要です。
File.Copy(source, copyDest, overwrite: true);
Console.WriteLine("上書きコピー完了");
// File.Move() でファイルを移動(またはリネーム)します。
File.Move(copyDest, moveDest);
Console.WriteLine($"移動前のコピー先: {File.Exists(copyDest)}"); // False
Console.WriteLine($"移動後の移動先: {File.Exists(moveDest)}"); // True
// ファイルの最終更新日時を取得します。
DateTime lastWrite = File.GetLastWriteTime(source);
Console.WriteLine($"最終更新: {lastWrite:yyyy/MM/dd HH:mm:ss}");
// File.Delete() でファイルを削除します。
File.Delete(source);
File.Delete(moveDest);
Console.WriteLine($"削除後: {File.Exists(source)}"); // False
dotnet script file_exists_delete_copy.csx True False コピー完了: True 上書きコピー完了 移動前のコピー先: False 移動後の移動先: True 最終更新: 2024/01/15 14:30:00 削除後: False
実践パターン: ファイルのバックアップと整理
設定ファイルを更新する前にバックアップを取り、古いファイルを削除するパターンです。
FileBackup.cs
using System;
using System.IO;
string configFile = "config.json";
string backupFile = $"config_{DateTime.Now:yyyyMMdd_HHmmss}.bak";
// テスト用設定ファイルを作成します。
File.WriteAllText(configFile, "{\"theme\": \"dark\"}");
Console.WriteLine("設定ファイル作成完了");
// 更新前にバックアップを作成します。
if (File.Exists(configFile))
{
File.Copy(configFile, backupFile);
Console.WriteLine($"バックアップ作成: {backupFile}");
}
// 設定ファイルを更新します。
File.WriteAllText(configFile, "{\"theme\": \"light\", \"fontSize\": 14}");
Console.WriteLine("設定ファイル更新完了");
// バックアップが存在することを確認します。
Console.WriteLine($"バックアップ存在: {File.Exists(backupFile)}");
Console.WriteLine($"バックアップ更新日時: {File.GetLastWriteTime(backupFile):yyyy/MM/dd HH:mm:ss}");
// 後片付けします。
File.Delete(configFile);
File.Delete(backupFile);
dotnet script file_backup.csx 設定ファイル作成完了 バックアップ作成: config_20240115_143045.bak 設定ファイル更新完了 バックアップ存在: True バックアップ更新日時: 2024/01/15 14:30:45
実践パターン: 安全なファイル操作(例外処理との組み合わせ)
File.Exists() と例外処理を組み合わせて、競合状態(TOCTOU)に対応した安全なファイル操作を行うパターンです。
SafeFileOps.cs
using System;
using System.IO;
// 安全なファイル削除:存在確認 + 例外処理
static bool TryDeleteFile(string path)
{
try
{
File.Delete(path);
return true;
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"権限エラー: {ex.Message}");
return false;
}
catch (IOException ex)
{
Console.WriteLine($"IO エラー: {ex.Message}");
return false;
}
}
// 安全なファイルコピー:上書き前に確認
static bool TryCopyFile(string src, string dest, bool overwrite = false)
{
if (!File.Exists(src))
{
Console.WriteLine($"コピー元が見つかりません: {src}");
return false;
}
try
{
File.Copy(src, dest, overwrite);
return true;
}
catch (IOException ex)
{
Console.WriteLine($"コピーエラー: {ex.Message}");
return false;
}
}
// テスト
File.WriteAllText("source.txt", "data");
bool ok1 = TryCopyFile("source.txt", "dest.txt");
bool ok2 = TryCopyFile("none.txt", "dest.txt"); // 失敗
bool ok3 = TryDeleteFile("source.txt");
bool ok4 = TryDeleteFile("dest.txt");
Console.WriteLine($"コピー1: {ok1}, コピー2: {ok2}, 削除1: {ok3}, 削除2: {ok4}");
dotnet script safe_file_ops.csx コピー元が見つかりません: none.txt コピー1: True, コピー2: False, 削除1: True, 削除2: True
よくあるミス
よくあるミス1: 上書きコピーで IOException
コピー先に既存ファイルがある場合、overwrite を指定しないと IOException がスローされます。
using System;
using System.IO;
File.WriteAllText("a.txt", "data1");
File.WriteAllText("b.txt", "data2"); // コピー先に既存ファイル
// NG: overwrite 未指定でコピー先に既存ファイルがあると例外が発生します。
File.Copy("a.txt", "b.txt");
dotnet run Unhandled exception. System.IO.IOException: The file 'b.txt' already exists.
修正後は次の通りです。
using System;
using System.IO;
File.WriteAllText("a.txt", "data1");
File.WriteAllText("b.txt", "data2");
// OK: overwrite: true で上書き許可します。
File.Copy("a.txt", "b.txt", overwrite: true);
Console.WriteLine("上書きコピー完了");
// 後片付けします。
File.Delete("a.txt");
File.Delete("b.txt");
dotnet run 上書きコピー完了
よくあるミス2: 読み取り専用ファイルの削除
読み取り専用属性が付いたファイルを File.Delete() で削除しようとすると UnauthorizedAccessException がスローされます。
using System;
using System.IO;
File.WriteAllText("readonly.txt", "data");
File.SetAttributes("readonly.txt", FileAttributes.ReadOnly);
// NG: 読み取り専用ファイルは削除できません。
File.Delete("readonly.txt"); // UnauthorizedAccessException が発生します。
dotnet run Unhandled exception. System.UnauthorizedAccessException: Access to the path 'readonly.txt' is denied.
修正後は次の通りです。
using System;
using System.IO;
File.WriteAllText("readonly.txt", "data");
File.SetAttributes("readonly.txt", FileAttributes.ReadOnly);
// OK: 読み取り専用属性を解除してから削除します。
File.SetAttributes("readonly.txt", FileAttributes.Normal);
File.Delete("readonly.txt");
Console.WriteLine("削除完了");
dotnet run 削除完了
概要
『File.Exists()』は競合状態(TOCTOU)の問題があります。「存在を確認 → 操作」の間に別プロセスがファイルを削除する可能性があるため、存在確認後も例外処理を組み合わせることが推奨されます。
『File.Delete()』は存在しないファイルに対しては何もしませんが、ファイルが読み取り専用の場合は UnauthorizedAccessException がスローされます。ファイルの一括読み書きについてはFile.ReadAllText() / WriteAllText()を、行単位のストリーム処理についてはStreamReader / StreamWriterをご確認ください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。