C#でファイル存在チェックする方法|File.Existsの使い方とfalseになる原因を解説
はじめに
C#でファイルを読み込んだり、削除したり、更新したりする前には、対象のファイルが存在するか確認したい場面があります。そのようなときに利用できるのが、System.IO.FileクラスのFile.Existsメソッドです。
File.Existsを使用すると、指定したパスにファイルが存在する場合はtrue、存在しない場合はfalseを取得できます。
ただし、実際にはファイルが存在しているにもかかわらず、パスの指定方法やアクセス権限などが原因でfalseになることがあります。また、File.Existsはフォルダの存在チェックやワイルドカードを使った検索には対応していません。
この記事では、C#でFile.Existsを使ってファイルの存在をチェックする基本的な方法から、falseになる原因、デバッグ方法、フォルダや複数ファイルを確認する方法まで詳しく解説します。
1. C#でファイルの存在をチェックする基本
1-1. File.Existsメソッドとは
File.Existsは、指定したパスにファイルが存在するかどうかを確認するための静的メソッドです。
基本的な構文は次のとおりです。
C#bool exists = File.Exists("ファイルパス");
引数には、確認したいファイルのパスを文字列で指定します。
たとえば、C:\data\sample.txtというファイルが存在するか確認する場合は、次のように記述します。
C#bool exists = File.Exists(@"C:\data\sample.txt");
File.Existsは静的メソッドなので、Fileクラスのインスタンスを作成する必要はありません。
1-2. File.Existsの戻り値(true・false)
File.Existsの戻り値はbool型です。
指定したパスにファイルが存在し、存在を確認できた場合はtrueを返します。
C#bool exists = File.Exists(@"C:\data\sample.txt");
Console.WriteLine(exists);
ファイルが存在する場合の出力結果は次のとおりです。
True
一方、ファイルが存在しない場合や、何らかの理由で存在を確認できない場合はfalseを返します。
False
falseになるのは、単純にファイルが存在しない場合だけではありません。パスの間違い、アクセス権限の不足、ネットワーク障害なども原因になります。
そのため、File.Existsがfalseを返したからといって、必ずしもファイル自体が存在しないとは限らない点に注意が必要です。
1-3. File.Existsを使用するためのSystem.IOの読み込み
FileクラスはSystem.IO名前空間に含まれています。
ソースコードの先頭で、次のようにSystem.IOを読み込みます。
C#using System.IO;
これにより、クラス名だけでFile.Existsを呼び出せます。
C#using System;
using System.IO;
class Program
{
static void Main()
{
bool exists = File.Exists(@"C:\data\sample.txt");
Console.WriteLine(exists);
}
}
using System.IO;を記述しない場合は、完全修飾名を使用することもできます。
C#bool exists = System.IO.File.Exists(@"C:\data\sample.txt");
2. File.Existsの基本的な使い方
2-1. 絶対パスを指定して存在チェックする方法
絶対パスとは、ドライブ名やルートディレクトリから始まる完全なファイルパスです。
Windowsでは、次のような形式になります。
C:\data\sample.txt
絶対パスを指定してファイルの存在を確認するコードは次のとおりです。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string filePath = @"C:\data\sample.txt";
bool exists = File.Exists(filePath);
Console.WriteLine(exists);
}
}
絶対パスは参照先が明確であるため、相対パスよりも実行環境による影響を受けにくいという利点があります。
ただし、特定の端末にしか存在しないパスをコードへ直接記述すると、別の端末では動作しない可能性があります。実際のアプリケーションでは、設定ファイルや環境変数からパスを取得する方法も検討しましょう。
2-2. 相対パスを指定して存在チェックする方法
File.Existsには相対パスも指定できます。
C#string filePath = @"data\sample.txt";
bool exists = File.Exists(filePath);
Console.WriteLine(exists);
相対パスは、通常、アプリケーションのカレントディレクトリを基準に解決されます。
たとえば、カレントディレクトリが次の場所だったとします。
C:\MyApp
この状態で次の相対パスを指定した場合、
data\sample.txt
実際に確認されるパスは次のようになります。
C:\MyApp\data\sample.txt
相対パスは環境に依存しないコードを書きやすい一方で、カレントディレクトリが想定と異なるとFile.Existsがfalseになるため注意が必要です。
2-3. if文でファイルの有無に応じて処理を分岐する方法
一般的には、File.Existsの結果をif文で判定します。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string filePath = @"C:\data\sample.txt";
if (File.Exists(filePath))
{
Console.WriteLine("ファイルが存在します。");
}
else
{
Console.WriteLine("ファイルが存在しません。");
}
}
}
戻り値を変数に格納せず、そのままif文の条件として使用できます。
否定演算子!を使用すれば、ファイルが存在しない場合の処理を先に記述することもできます。
C#if (!File.Exists(filePath))
{
Console.WriteLine("ファイルが見つかりません。");
return;
}
Console.WriteLine("ファイルを読み込みます。");
この書き方は、ファイルが存在しない場合に処理を早期終了したいときに便利です。
2-4. ファイルが存在しない場合に作成する方法
ファイルが存在しない場合だけ、新しいファイルを作成する例は次のとおりです。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string filePath = @"C:\data\sample.txt";
if (!File.Exists(filePath))
{
File.WriteAllText(filePath, "新しいファイルです。");
Console.WriteLine("ファイルを作成しました。");
}
else
{
Console.WriteLine("ファイルはすでに存在します。");
}
}
}
File.WriteAllTextは、指定したファイルに文字列を書き込みます。ファイルが存在しない場合は新規作成され、存在する場合は内容が上書きされます。
空のファイルを作成したい場合は、File.Createも利用できます。
C#if (!File.Exists(filePath))
{
using FileStream stream = File.Create(filePath);
}
File.Createは、開かれたFileStreamを返します。使用後にストリームを閉じる必要があるため、usingを使用して確実に破棄しましょう。
なお、存在チェックの直後に別の処理がファイルを作成する可能性があります。競合が問題になる処理では、存在チェックだけに依存せず、ファイル作成時の例外処理も実装する必要があります。
3. File.Existsで指定するファイルパスの書き方
3-1. Windowsのパスを逐語的文字列リテラル(@)で記述する
C#の文字列では、バックスラッシュ\がエスケープ文字として使用されます。
そのため、Windowsのパスをそのまま書きたい場合は、文字列の先頭に@を付ける逐語的文字列リテラルが便利です。
C#string filePath = @"C:\data\sample.txt";
@を付けると、バックスラッシュをエスケープせずに記述できます。
次のような深い階層のパスでも読みやすくなります。
C#string filePath = @"C:\Users\user\Documents\reports\2026\report.txt";
ただし、逐語的文字列リテラル内でダブルクォーテーションを使用する場合は、""のように2つ続けて記述します。
3-2. バックスラッシュをエスケープして記述する
通常の文字列リテラルでWindowsのパスを指定する場合は、バックスラッシュを\\と記述します。
C#string filePath = "C:\\data\\sample.txt";
このコードが表す実際の文字列は次のとおりです。
C:\data\sample.txt
次のようにバックスラッシュを1つだけ記述すると、\tや\nなどがタブや改行として解釈される可能性があります。
C#// 推奨されない書き方
string filePath = "C:\temp\new.txt";
Windowsパスには、逐語的文字列リテラルを使うか、バックスラッシュを正しくエスケープしてください。
3-3. Path.Combineで安全にパスを結合する
フォルダ名とファイル名を結合するときは、文字列を直接連結するよりもPath.Combineを使用する方法が安全です。
C#string directoryPath = @"C:\data";
string fileName = "sample.txt";
string filePath = Path.Combine(directoryPath, fileName);
Console.WriteLine(filePath);
出力結果は次のようになります。
C:\data\sample.txt
文字列連結では、区切り文字の有無を自分で管理しなければなりません。
C#string filePath = directoryPath + "\\" + fileName;
Path.Combineを使用すれば、区切り文字を適切に処理できます。
複数階層のパスもまとめて結合できます。
C#string filePath = Path.Combine(
@"C:\data",
"reports",
"2026",
"report.txt"
);
アプリケーションの実行場所を基準にする場合は、AppContext.BaseDirectoryと組み合わせる方法もあります。
C#string filePath = Path.Combine(
AppContext.BaseDirectory,
"data",
"sample.txt"
);
bool exists = File.Exists(filePath);
3-4. カレントディレクトリと相対パスの関係を確認する
相対パスがどこを基準に解決されているか確認するには、Directory.GetCurrentDirectoryを使用します。
C#string currentDirectory = Directory.GetCurrentDirectory();
Console.WriteLine(currentDirectory);
相対パスと組み合わせて、実際に確認される絶対パスを表示することもできます。
C#string relativePath = @"data\sample.txt";
string fullPath = Path.GetFullPath(relativePath);
Console.WriteLine(fullPath);
Console.WriteLine(File.Exists(relativePath));
Visual Studioからアプリケーションを実行した場合、プロジェクトフォルダではなく、ビルド出力先などが基準になることがあります。
たとえば、次のようなディレクトリです。
プロジェクトフォルダ\bin\Debug\net8.0
プロジェクト内に置いたファイルを実行時に参照したい場合は、ファイルのプロパティで出力ディレクトリへのコピー設定も確認しましょう。
3-5. 拡張子を含む正しいファイル名を指定する
File.Existsでは、拡張子を含めた実際のファイル名を指定する必要があります。
実際のファイル名がsample.txtの場合、次の指定では一致しません。
C#File.Exists(@"C:\data\sample");
正しくは次のように指定します。
C#File.Exists(@"C:\data\sample.txt");
Windowsのエクスプローラーでは、設定によって登録済みファイルの拡張子が非表示になることがあります。
画面上でsampleと表示されていても、実際の名前が次のようになっている可能性があります。
sample.txt
sample.txt.txt
sample.csv
File.Existsが想定外にfalseになる場合は、エクスプローラーで拡張子を表示し、実際のファイル名を確認してください。
4. ファイルが存在するのにFile.Existsがfalseになる原因
4-1. 指定したファイルパスが間違っている
最も多い原因は、指定したファイルパスの間違いです。
たとえば、実際のフォルダ名がdocumentsなのに、コードでdocumentと指定している場合はfalseになります。
C#string filePath = @"C:\document\sample.txt";
次の点を確認しましょう。
ドライブ名が正しいか
フォルダ名が正しいか
ファイル名が正しいか
パスの区切りが正しいか
ファイルが別のフォルダへ移動していないか
目視だけでは違いに気づきにくいため、パスをエクスプローラーのアドレス欄からコピーして比較する方法が有効です。
4-2. 相対パスの基準となるカレントディレクトリが想定と異なる
相対パスは、ソースコードの保存場所ではなく、実行時のカレントディレクトリを基準に解決されます。
次のコードを実行して、基準となる場所を確認してください。
C#Console.WriteLine(Directory.GetCurrentDirectory());
また、Path.GetFullPathを使うと、相対パスがどの絶対パスに変換されているか確認できます。
C#string filePath = @"data\sample.txt";
Console.WriteLine(Path.GetFullPath(filePath));
Console.WriteLine(File.Exists(filePath));
実行方法やホスト環境によってカレントディレクトリが変わる可能性があるため、アプリケーションの配置先を基準にしたい場合はAppContext.BaseDirectoryを使用します。
C#string filePath = Path.Combine(
AppContext.BaseDirectory,
"data",
"sample.txt"
);
4-3. ファイル名や拡張子が一致していない
ファイル名の入力ミスや拡張子の違いも、falseになる原因です。
たとえば、次のファイルはそれぞれ別の名前です。
report.txt
report.csv
report.txt.txt
report_2026.txt
プログラムで生成したファイル名には、日付や連番が含まれていることもあります。変数を組み合わせてファイル名を生成している場合は、完成したパスを出力して確認しましょう。
C#string fileName = $"report_{DateTime.Now:yyyyMMdd}.txt";
string filePath = Path.Combine(@"C:\data", fileName);
Console.WriteLine(filePath);
Linuxなど、大文字と小文字を区別するファイルシステムでは、Sample.txtとsample.txtが別のファイルとして扱われる点にも注意が必要です。
4-4. パスに余分な空白や改行が含まれている
設定ファイル、CSV、テキストボックスなどからパスを取得すると、文字列の前後に空白や改行が含まれることがあります。
C#string filePath = "C:\\data\\sample.txt\r\n";
見た目では気づきにくくても、実際には別のパスとして判定されます。
文字列の前後にある不要な空白や改行は、Trimで除去できます。
C#string filePath = inputPath.Trim();
bool exists = File.Exists(filePath);
ただし、ファイル名の先頭や末尾に意図的な空白が含まれる特殊なケースでは、無条件にTrimすると別の名前になる可能性があります。入力元の仕様を確認したうえで使用してください。
制御文字を確認したい場合は、文字列をダブルクォーテーションで囲んで出力すると見つけやすくなります。
C#Console.WriteLine($"Path: [{filePath}]");
文字コードを調べる方法もあります。
C#foreach (char character in filePath)
{
Console.WriteLine(
$"'{character}' U+{(int)character:X4}"
);
}
4-5. フォルダのパスをFile.Existsに指定している
File.Existsは、ファイルの存在を確認するメソッドです。フォルダのパスを指定した場合は、通常falseになります。
C#bool exists = File.Exists(@"C:\data");
Console.WriteLine(exists);
C:\dataというフォルダが存在していても、ファイルではないため結果はfalseです。
フォルダの存在を確認する場合は、Directory.Existsを使用します。
C#bool exists = Directory.Exists(@"C:\data");
4-6. ファイルやフォルダへのアクセス権限がない
実行ユーザーに対象ファイルやフォルダへのアクセス権限がない場合、File.Existsがfalseを返すことがあります。
特に、次のような場所では権限の影響を受けやすくなります。
管理者だけがアクセスできるフォルダ
他のユーザーのプロファイルフォルダ
サーバー上の共有フォルダ
Webアプリケーションから参照するローカルフォルダ
Windowsサービスから参照するフォルダ
開発中のユーザーアカウントでは参照できても、公開環境のアプリケーション実行ユーザーでは参照できない場合があります。
ASP.NET Core、IIS、Windowsサービス、タスクスケジューラなどを使用している場合は、実際の実行ユーザーとフォルダのアクセス許可を確認してください。
4-7. ネットワークドライブや共有フォルダに接続できていない
ネットワーク上のファイルを確認している場合は、接続状態によってfalseになることがあります。
たとえば、次のような原因が考えられます。
サーバーが停止している
ネットワークに接続できない
VPNへ接続していない
共有フォルダの名前が変わった
認証情報が無効になった
実行ユーザーに共有フォルダの権限がない
また、ドライブレターを割り当てたネットワークドライブは、ユーザーごとに接続状態が異なる場合があります。
C#string filePath = @"Z:\shared\sample.txt";
開発者がログインしている画面ではZ:ドライブが見えていても、WindowsサービスやIISの実行ユーザーには見えない可能性があります。
このような場合は、UNCパスを使用する方法があります。
C#string filePath = @"\\server-name\shared\sample.txt";
4-8. パスに無効な文字が含まれている
パスに使用できない文字や、不正な形式が含まれていると、ファイルの存在を正しく確認できません。
ユーザー入力からファイル名を作る場合は、使用できない文字が含まれていないか確認します。
C#char[] invalidChars = Path.GetInvalidFileNameChars();
bool containsInvalidChar =
fileName.IndexOfAny(invalidChars) >= 0;
検出例は次のとおりです。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string fileName = "sample?.txt";
char[] invalidChars = Path.GetInvalidFileNameChars();
if (fileName.IndexOfAny(invalidChars) >= 0)
{
Console.WriteLine("ファイル名に使用できない文字が含まれています。");
}
}
}
ファイル名だけでなく、パス全体の生成処理に誤りがないかも確認してください。
4-9. パスが長すぎる、またはドライブに問題がある
実行環境やOSの設定によっては、非常に長いパスを正しく処理できないことがあります。
また、次のようなドライブ側の問題でも、ファイルを確認できない場合があります。
外付けドライブが取り外されている
USBメモリが認識されていない
ドライブレターが変更された
ネットワークドライブが切断されている
ディスクやファイルシステムに問題がある
ドライブの存在は、DriveInfoを使用して確認できます。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string driveName = @"D:\";
var drive = new DriveInfo(driveName);
if (drive.IsReady)
{
Console.WriteLine("ドライブを利用できます。");
}
else
{
Console.WriteLine("ドライブを利用できません。");
}
}
}
DriveInfoの生成やプロパティの取得では例外が発生する可能性があるため、外部ドライブを扱う実際の処理では例外処理も必要です。
5. File.Existsがfalseになる場合の確認・デバッグ方法
5-1. 実際に判定しているパスをログやコンソールに出力する
最初に確認すべきなのは、File.Existsへ渡している実際の文字列です。
C#string filePath = GetFilePath();
Console.WriteLine($"確認するパス: [{filePath}]");
Console.WriteLine($"存在するか: {File.Exists(filePath)}");
変数を組み合わせてパスを作成している場合、途中の値も出力します。
C#Console.WriteLine($"フォルダ: [{directoryPath}]");
Console.WriteLine($"ファイル名: [{fileName}]");
Console.WriteLine($"完成したパス: [{filePath}]");
本番環境では、利用しているロギングライブラリを使って記録すると調査しやすくなります。
ただし、ユーザー名や機密情報を含むパスをログへ出力する場合は、情報漏えいに注意してください。
5-2. Path.GetFullPathで絶対パスを確認する
相対パスを使用している場合は、Path.GetFullPathで絶対パスへ変換します。
C#string relativePath = @"data\sample.txt";
try
{
string fullPath = Path.GetFullPath(relativePath);
Console.WriteLine($"絶対パス: {fullPath}");
Console.WriteLine($"存在するか: {File.Exists(fullPath)}");
}
catch (Exception ex)
{
Console.WriteLine($"パスの変換に失敗しました: {ex.Message}");
}
出力された絶対パスをエクスプローラーなどで開き、目的のファイルが本当に存在するか確認します。
Path.GetFullPathは、パスの形式に問題があると例外を発生させる可能性があります。デバッグ時には、例外の内容も原因特定の手がかりになります。
5-3. Directory.GetCurrentDirectoryでカレントディレクトリを確認する
相対パスの基準は、次のコードで確認できます。
C#string currentDirectory =
Directory.GetCurrentDirectory();
Console.WriteLine(
$"カレントディレクトリ: {currentDirectory}"
);
アプリケーション本体が配置された場所も確認しておくと、両者の違いを把握できます。
C#Console.WriteLine(
$"ベースディレクトリ: {AppContext.BaseDirectory}"
);
Directory.GetCurrentDirectory()とAppContext.BaseDirectoryは、常に同じとは限りません。
アプリケーションと一緒に配置したファイルを参照する場合は、次のようにベースディレクトリからパスを作ると意図が明確になります。
C#string filePath = Path.Combine(
AppContext.BaseDirectory,
"data",
"sample.txt"
);
5-4. 文字列の前後に空白や制御文字がないか確認する
パスを角括弧などで囲んで出力すると、前後の空白を見つけやすくなります。
C#Console.WriteLine($"[{filePath}]");
Console.WriteLine($"文字数: {filePath.Length}");
前後の空白や改行を削除した結果と比較する方法もあります。
C#string trimmedPath = filePath.Trim();
Console.WriteLine($"変更前: [{filePath}]");
Console.WriteLine($"変更後: [{trimmedPath}]");
Console.WriteLine($"同じ文字列か: {filePath == trimmedPath}");
不可視文字を詳細に確認する場合は、各文字のUnicodeコードポイントを出力します。
C#for (int i = 0; i < filePath.Length; i++)
{
char character = filePath[i];
Console.WriteLine(
$"{i}: '{character}' U+{(int)character:X4}"
);
}
U+000Dはキャリッジリターン、U+000Aは改行、U+0009はタブです。
5-5. 実行ユーザーとアクセス権限を確認する
Windows環境では、次のコードで実行ユーザーを確認できます。
C#using System;
using System.Security.Principal;
class Program
{
static void Main()
{
string? userName =
WindowsIdentity.GetCurrent().Name;
Console.WriteLine($"実行ユーザー: {userName}");
}
}
確認したユーザーが、対象ファイルや親フォルダへのアクセス権限を持っているか調べます。
特にサーバー上では、開発者が操作しているユーザーと、アプリケーションを実行しているユーザーが異なるケースが一般的です。
権限不足を詳しく確認したい場合は、存在チェックだけではなく、実際にファイルを開き、発生した例外を記録する方法が有効です。
C#try
{
using FileStream stream = File.OpenRead(filePath);
Console.WriteLine("ファイルを開けました。");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine(
$"アクセス権限がありません: {ex.Message}"
);
}
catch (IOException ex)
{
Console.WriteLine(
$"入出力エラーが発生しました: {ex.Message}"
);
}
5-6. UNCパスを使って共有ファイルの存在を確認する
ネットワークドライブの代わりにUNCパスを使用すると、参照先を明確にできます。
C#string filePath =
@"\\server-name\shared-folder\data\sample.txt";
bool exists = File.Exists(filePath);
Console.WriteLine(exists);
UNCパスは、次の形式で記述します。
\\サーバー名\共有名\フォルダ名\ファイル名
ただし、UNCパスに変更しても、実行ユーザーに共有フォルダへのアクセス権限がなければ確認できません。
共有側のアクセス許可、NTFSアクセス許可、認証情報、ネットワーク接続を合わせて確認してください。
6. フォルダの存在をチェックする方法
6-1. Directory.Existsの基本的な使い方
フォルダの存在を確認する場合は、Directory.Existsを使用します。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string directoryPath = @"C:\data";
if (Directory.Exists(directoryPath))
{
Console.WriteLine("フォルダが存在します。");
}
else
{
Console.WriteLine("フォルダが存在しません。");
}
}
}
Directory.Existsも、存在する場合はtrue、存在しない場合や確認できない場合はfalseを返します。
6-2. File.ExistsとDirectory.Existsの違い
File.ExistsとDirectory.Existsでは、確認する対象が異なります。
| メソッド | 確認対象 |
|---|---|
File.Exists | ファイル |
Directory.Exists | フォルダ |
同じパスを指定しても、対象の種類によって結果が変わります。
C#string path = @"C:\data";
Console.WriteLine(File.Exists(path));
Console.WriteLine(Directory.Exists(path));
C:\dataがフォルダとして存在する場合、結果は次のようになります。
False
True
ファイルパスに対してDirectory.Existsを実行した場合も、通常はfalseになります。
6-3. ファイルとフォルダのどちらかが存在するか判定する方法
パスがファイルまたはフォルダのどちらかとして存在するか確認する場合は、両方のメソッドを組み合わせます。
C#string path = @"C:\data\sample.txt";
bool exists =
File.Exists(path) ||
Directory.Exists(path);
Console.WriteLine(exists);
対象の種類も判定したい場合は、条件を分けます。
C#if (File.Exists(path))
{
Console.WriteLine("ファイルとして存在します。");
}
else if (Directory.Exists(path))
{
Console.WriteLine("フォルダとして存在します。");
}
else
{
Console.WriteLine("存在しません。");
}
6-4. フォルダが存在しない場合に作成する方法
フォルダが存在しない場合は、Directory.CreateDirectoryで作成できます。
C#string directoryPath = @"C:\data\reports";
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
Console.WriteLine("フォルダを作成しました。");
}
Directory.CreateDirectoryは、中間のフォルダが存在しない場合もまとめて作成します。
C#Directory.CreateDirectory(
@"C:\data\reports\2026\06"
);
また、対象のフォルダがすでに存在していても、通常はそのことだけを理由に例外にはなりません。そのため、単純にフォルダを用意したい場合は、存在チェックを省略して次のように記述できます。
C#Directory.CreateDirectory(directoryPath);
ファイルを作成する前に、親フォルダを確実に用意する例は次のとおりです。
C#string directoryPath = @"C:\data\reports";
string filePath =
Path.Combine(directoryPath, "report.txt");
Directory.CreateDirectory(directoryPath);
File.WriteAllText(filePath, "レポート内容");
7. ファイル名の一部や拡張子を指定して存在チェックする方法
7-1. File.Existsでワイルドカードを使用できない理由
File.Existsは、1つの具体的なファイルパスを確認するメソッドです。
そのため、*や?などのワイルドカードを指定して複数のファイルを検索することはできません。
C#bool exists =
File.Exists(@"C:\data\*.txt");
C:\data内にテキストファイルが存在していても、このコードで期待した結果は得られません。
ワイルドカードを使用したい場合は、Directory.GetFilesまたはDirectory.EnumerateFilesを使用します。
7-2. Directory.GetFilesで条件に一致するファイルを検索する
Directory.GetFilesを使用すると、検索パターンに一致するファイルのパスを配列として取得できます。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string directoryPath = @"C:\data";
string[] files =
Directory.GetFiles(
directoryPath,
"*.txt"
);
if (files.Length > 0)
{
Console.WriteLine(
"テキストファイルが存在します。"
);
}
}
}
取得したファイルを一覧表示することもできます。
C#foreach (string file in files)
{
Console.WriteLine(file);
}
サブフォルダを含めて検索する場合は、SearchOption.AllDirectoriesを指定します。
C#string[] files = Directory.GetFiles(
directoryPath,
"*.txt",
SearchOption.AllDirectories
);
サブフォルダの検索では、アクセス権限がないフォルダなどで例外が発生する可能性があります。対象範囲が大きい場合は、パフォーマンスにも注意してください。
7-3. EnumerateFilesとAnyで効率的に存在チェックする
条件に一致するファイルが1件でも存在するか確認するだけなら、Directory.EnumerateFilesとLINQのAnyを組み合わせる方法があります。
C#using System;
using System.IO;
using System.Linq;
class Program
{
static void Main()
{
string directoryPath = @"C:\data";
bool exists = Directory
.EnumerateFiles(directoryPath, "*.txt")
.Any();
Console.WriteLine(exists);
}
}
Directory.GetFilesは、条件に一致するファイルをすべて取得して配列を作成します。
一方、EnumerateFilesは列挙しながら処理できるため、最初の一致が見つかった時点で判定を終えられるAnyと相性がよい方法です。
フォルダが存在しない場合、EnumerateFilesは例外を発生させる可能性があります。先にフォルダの存在を確認すると安全です。
C#bool exists =
Directory.Exists(directoryPath) &&
Directory
.EnumerateFiles(directoryPath, "*.txt")
.Any();
7-4. 複数の拡張子を対象にファイルを検索する
複数の拡張子を対象にする場合は、取得したファイルの拡張子を判定します。
C#using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
static void Main()
{
string directoryPath = @"C:\data";
var targetExtensions =
new HashSet<string>(
StringComparer.OrdinalIgnoreCase
)
{
".jpg",
".jpeg",
".png",
".gif"
};
bool exists =
Directory.Exists(directoryPath) &&
Directory
.EnumerateFiles(directoryPath)
.Any(file =>
targetExtensions.Contains(
Path.GetExtension(file)
)
);
Console.WriteLine(exists);
}
}
StringComparer.OrdinalIgnoreCaseを指定すると、.JPGや.Pngなど、大文字と小文字が異なる拡張子も同じものとして判定できます。
対象ファイルを一覧で取得する場合は、Whereを使用します。
C#IEnumerable<string> imageFiles =
Directory
.EnumerateFiles(directoryPath)
.Where(file =>
targetExtensions.Contains(
Path.GetExtension(file)
)
);
foreach (string file in imageFiles)
{
Console.WriteLine(file);
}
8. FileInfo.Existsを使って存在チェックする方法
8-1. FileInfo.Existsの基本的な使い方
FileInfoクラスを使用してファイルの存在を確認することもできます。
C#using System;
using System.IO;
class Program
{
static void Main()
{
var fileInfo =
new FileInfo(@"C:\data\sample.txt");
if (fileInfo.Exists)
{
Console.WriteLine("ファイルが存在します。");
}
else
{
Console.WriteLine("ファイルが存在しません。");
}
}
}
FileInfo.Existsはメソッドではなく、bool型のプロパティです。
C#bool exists = fileInfo.Exists;
8-2. File.ExistsとFileInfo.Existsの違い
File.Existsは静的メソッドであり、パスを指定して簡単に存在チェックできます。
C#bool exists =
File.Exists(@"C:\data\sample.txt");
FileInfo.Existsでは、最初にFileInfoオブジェクトを作成します。
C#var fileInfo =
new FileInfo(@"C:\data\sample.txt");
bool exists = fileInfo.Exists;
存在確認だけが目的なら、File.Existsのほうが簡潔です。
一方、ファイルサイズ、更新日時、拡張子なども続けて取得したい場合は、FileInfoが便利です。
8-3. FileInfoでサイズや更新日時も取得する方法
FileInfoを使うと、ファイルに関するさまざまな情報を取得できます。
C#var fileInfo =
new FileInfo(@"C:\data\sample.txt");
if (fileInfo.Exists)
{
Console.WriteLine($"名前: {fileInfo.Name}");
Console.WriteLine($"フルパス: {fileInfo.FullName}");
Console.WriteLine($"拡張子: {fileInfo.Extension}");
Console.WriteLine($"サイズ: {fileInfo.Length} bytes");
Console.WriteLine(
$"更新日時: {fileInfo.LastWriteTime}"
);
}
主なプロパティは次のとおりです。
| プロパティ | 内容 |
|---|---|
Name | ファイル名 |
FullName | 絶対パス |
Extension | 拡張子 |
Length | ファイルサイズ |
CreationTime | 作成日時 |
LastWriteTime | 最終更新日時 |
DirectoryName | 親フォルダのパス |
Lengthなど、一部のプロパティはファイルが存在しない状態で取得すると例外になる可能性があります。先にExistsを確認してください。
ただし、確認直後にファイルが削除される可能性もあるため、実際の処理では例外対策も必要です。
8-4. FileInfoの情報を再取得するときの注意点
FileInfoのプロパティ情報はキャッシュされることがあります。
FileInfoオブジェクトを作成したあとでファイルの状態が変化した場合、最新の情報を取得するためにRefreshを使用します。
C#var fileInfo =
new FileInfo(@"C:\data\sample.txt");
Console.WriteLine(fileInfo.Exists);
// 別の処理によってファイルの状態が変化した可能性がある
fileInfo.Refresh();
Console.WriteLine(fileInfo.Exists);
ファイルサイズや更新日時を再確認する場合も、必要に応じてRefreshを呼び出します。
C#fileInfo.Refresh();
if (fileInfo.Exists)
{
Console.WriteLine(fileInfo.Length);
Console.WriteLine(fileInfo.LastWriteTime);
}
9. File.Existsを使用するときの注意点
9-1. File.Existsはエラーが発生しても例外ではなくfalseを返す
File.Existsは、ファイルが存在しない場合だけでなく、存在を確認できない場合にもfalseを返します。
たとえば、次のようなケースです。
パスの形式が正しくない
アクセス権限がない
ネットワークへ接続できない
ドライブを利用できない
指定したパスがフォルダである
パスが
nullまたは空文字である
C#Console.WriteLine(File.Exists(null));
Console.WriteLine(File.Exists(""));
どちらも通常はfalseになります。
File.Existsだけでは、なぜfalseになったのかを特定できません。原因を詳しく調査する必要がある場合は、パスや実行環境を確認し、実際のファイル操作で発生する例外を記録します。
9-2. 存在チェック直後にファイルが削除される可能性がある
次のコードでは、存在確認と読み込みが別々の処理になっています。
C#if (File.Exists(filePath))
{
string content =
File.ReadAllText(filePath);
}
File.Existsがtrueを返した直後に、別のプログラムやスレッドがファイルを削除する可能性があります。
その場合、File.ReadAllTextでは例外が発生します。
反対に、File.Existsがfalseを返した直後に、別の処理がファイルを作成する可能性もあります。
このように、存在チェックの結果は、その瞬間の状態を示すものにすぎません。
9-3. 存在チェックだけでファイルを安全に操作できるとは限らない
ファイルが存在していても、必ず読み書きできるとは限りません。
次のような理由で操作に失敗する可能性があります。
読み取り権限がない
書き込み権限がない
他のプロセスがファイルを排他的に使用している
ファイルが破損している
ネットワーク接続が切断された
ディスク容量が不足している
ファイルが操作直前に移動または削除された
そのため、File.Existsを権限確認や操作可否の判定として使用することはできません。
ファイルを読み込めるかどうかを確認したい場合は、実際に読み込みを試み、例外を適切に処理する必要があります。
9-4. ファイルを開く処理では例外処理も実装する
ファイルの読み込みでは、tryとcatchを使用して例外を処理します。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string filePath =
@"C:\data\sample.txt";
try
{
string content =
File.ReadAllText(filePath);
Console.WriteLine(content);
}
catch (FileNotFoundException)
{
Console.WriteLine(
"ファイルが見つかりません。"
);
}
catch (DirectoryNotFoundException)
{
Console.WriteLine(
"フォルダが見つかりません。"
);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine(
"ファイルへのアクセス権限がありません。"
);
}
catch (IOException ex)
{
Console.WriteLine(
$"ファイルの読み込みに失敗しました: {ex.Message}"
);
}
}
}
必要な例外を個別に処理すると、ユーザーへの案内やログの内容を原因に応じて変更できます。
Exceptionだけをまとめて捕捉するよりも、想定される例外を具体的に処理するほうが、原因を判断しやすくなります。
9-5. 存在チェックとファイル操作を組み合わせた実践コード
設定ファイルが存在する場合は読み込み、存在しない場合は初期内容で作成する例を紹介します。
C#using System;
using System.IO;
class Program
{
static void Main()
{
string directoryPath = Path.Combine(
AppContext.BaseDirectory,
"config"
);
string filePath = Path.Combine(
directoryPath,
"settings.txt"
);
try
{
Directory.CreateDirectory(directoryPath);
if (!File.Exists(filePath))
{
File.WriteAllText(
filePath,
"language=ja"
);
Console.WriteLine(
"設定ファイルを作成しました。"
);
}
string content =
File.ReadAllText(filePath);
Console.WriteLine(
$"設定内容: {content}"
);
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine(
$"アクセス権限がありません: {ex.Message}"
);
}
catch (IOException ex)
{
Console.WriteLine(
$"ファイル操作に失敗しました: {ex.Message}"
);
}
}
}
このコードでは、次の処理を行っています。
AppContext.BaseDirectoryを基準にパスを作成するDirectory.CreateDirectoryで保存先フォルダを用意するFile.Existsで設定ファイルの有無を確認する存在しない場合は初期ファイルを作成する
ファイルを読み込む
ファイル操作に関する例外を処理する
ただし、複数のプロセスが同じファイルを同時に作成する可能性がある場合は、存在チェックと作成の間で競合が発生します。
上書きを避けて新規ファイルだけを作成したい場合は、FileMode.CreateNewを使用できます。
C#try
{
using FileStream stream = new FileStream(
filePath,
FileMode.CreateNew,
FileAccess.Write,
FileShare.None
);
using var writer =
new StreamWriter(stream);
writer.WriteLine("language=ja");
Console.WriteLine(
"新しいファイルを作成しました。"
);
}
catch (IOException)
{
Console.WriteLine(
"ファイルがすでに存在するか、作成できませんでした。"
);
}
FileMode.CreateNewは、対象ファイルがすでに存在する場合に例外を発生させます。存在チェックと作成を別々に行う方法よりも、意図しない上書きを防ぎやすくなります。
まとめ
C#でファイルの存在をチェックするには、System.IO.File.Existsを使用します。
C#bool exists =
File.Exists(@"C:\data\sample.txt");
File.Existsは、ファイルが存在する場合はtrue、存在しない場合や存在を確認できない場合はfalseを返します。
falseになる場合は、次の点を確認することが重要です。
指定したパスが正しいか
相対パスの基準が想定どおりか
ファイル名と拡張子が一致しているか
空白や改行が含まれていないか
フォルダのパスを指定していないか
実行ユーザーにアクセス権限があるか
ネットワークやドライブへ接続できているか
相対パスの問題を調べるときは、Path.GetFullPathとDirectory.GetCurrentDirectoryが役立ちます。
C#Console.WriteLine(
Path.GetFullPath(filePath)
);
Console.WriteLine(
Directory.GetCurrentDirectory()
);
フォルダの存在を確認する場合はDirectory.Exists、条件に一致する複数のファイルを探す場合はDirectory.EnumerateFilesなどを使用します。
また、File.Existsの結果は確認した瞬間の状態にすぎません。存在チェックの直後にファイルが削除されたり、アクセスできなくなったりする可能性があります。
実際にファイルを読み書きする処理では、File.Existsだけに依存せず、FileNotFoundException、UnauthorizedAccessException、IOExceptionなどを想定した例外処理も実装しましょう。

