私は現在、 を使用してさまざまなディレクトリを走査し、特定のファイルが存在することを確認するプログラムに取り組んでいますFile.Exists()
。
アプリケーションは、実際には存在する特定のファイルが存在しないと主張していましたが、最近、このエラーはパスが長すぎるために発生していることが分かりました。
SO には誤った値を返すことに関する質問があることは承知していますFile.Exists()
が、この特定の問題を解決しているものはありません。
ディレクトリとファイルの名前を変更してパスを短くすることは実際には選択肢ではないので、この時点で何をすべきかわかりません。この問題を解決する回避策はありますか?
使用されているコードは特別なものではありません (無関係なコードをいくつか削除しました) が、役立つ場合に備えて以下に含めます。
private void checkFile(string path)
{
if (!File.Exists(path))
Console.WriteLine(" * File: " + path + " does not exist.");
}
ベストアンサー1
Windows API では (次の段落で説明するいくつかの例外を除く)、パスの最大長は MAX_PATH で、260 文字と定義されています。
...
Windows API には、最大合計パス長が 32,767 文字の拡張パスを許可する Unicode バージョンも備えた関数が多数あります。この種類のパスは、バックスラッシュで区切られたコンポーネントで構成され、各コンポーネントの最大長は GetVolumeInformation 関数の lpMaximumComponentLength パラメータで返される値 (通常、この値は 255 文字) です。拡張長パスを指定するには、
"\\?\"
プレフィックスを使用します。たとえば、 です"\\?\D:\very long path"
。...
なぜなら
"\\?\"
相対パスでプレフィックスを使用することはできません相対パスは常に MAX_PATH 文字の合計に制限されます。
(強調追加)
すべてのパスがフルパスである場合は、次のように拡張長パス指定子を使用するようにコードを更新できます。
const longPathSpecifier = @"\\?";
private void checkFile(string path)
{
// Add the long-path specifier if it's missing
string longPath = (path.StartsWith(longPathSpecifier) ? path : longPathSpecifier + path);
if (!File.Exists(longPath))
{
// Print the original path
Console.WriteLine(" * File: " + path + " does not exist.");
}
}
アップデート:
ファイル I/O の場合、パス文字列のプレフィックス "\?\" は、Windows API にすべての文字列解析を無効にし、それに続く文字列をファイル システムに直接送信するように指示します。たとえば、ファイルシステムが長いパスとファイル名をサポートしているかどうか、Windows API によって強制される MAX_PATH 制限を超える可能性があります。
少なくとも私のシステム (Windows 7 を使用) では長いファイル名はサポートされていないため、上記の解決策が機能するかどうかは確認できません。
アップデート:実際に機能する解決策を見つけましたが、かなり見苦しいものでした。疑似コードで実行した結果は次のとおりです。
- パスをディレクトリの配列に分割する
- 260 文字未満のパスの最長部分 (MAX_PATH) を取得します。
- 作成するディレクトリ情報パスのその部分(将来の参照では「dir」)
- パス内の残りのディレクトリについては、
a. を呼び出してdir.GetDirectories()
、次のディレクトリが結果に含まれているかどうかを確認します
。b. 含まれている場合は、dir
そのディレクトリに設定しDirectoryInfo
て検索を続けます
。c. そうでない場合は、パスは存在しません。 - ファイルに至るまでのすべてのディレクトリを調べ終わったら、を呼び出して
dir.GetFiles()
、返されたオブジェクト内にファイルが存在するかどうかを確認しますFileInfo
。