[解決済み] フォルダが空かどうかをすばやく確認する方法(.NET)?
2022-04-26 04:24:50
質問
ディスク上のディレクトリが空であるかどうかを確認する必要があります。これは、フォルダやファイルが含まれていないことを意味します。私は、簡単な方法があることを知っています。FileSystemInfoの配列を取得し、要素のカウントがゼロになるかどうかをチェックします。そのようなものです。
public static bool CheckFolderEmpty(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
}
var folder = new DirectoryInfo(path);
if (folder.Exists)
{
return folder.GetFileSystemInfos().Length == 0;
}
throw new DirectoryNotFoundException();
}
このやり方は問題なさそうです。しかし!!パフォーマンスの観点からは非常に非常に悪いです。 GetFileSystemInfos() は非常にハードなメソッドです。実際、フォルダーのすべてのファイルシステムオブジェクトを列挙し、そのすべてのプロパティを取得し、オブジェクトを作成し、型付き配列を埋めるなどしています。そして、これらすべては、単に長さをチェックするためだけに行われます。バカみたいでしょう?
このようなコードをプロファイリングしたところ、このようなメソッドの250回の呼び出しが500msで実行されることがわかりました。これは非常に遅く、もっと速く実行することが可能だと思います。
何か提案はありますか?
解決方法は?
これは、私が最終的に実装した超高速ソリューションです。ここでは、WinAPIと関数を使っています。 FindFirstFile , FindNextFile . これにより、フォルダ内のすべてのアイテムの列挙を回避して フォルダ内の最初のオブジェクトを検出した直後に停止する。 . この方法は、上記の方法よりも6倍(!)高速です。250回の呼び出しで36ms!
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll")]
private static extern bool FindClose(IntPtr hFindFile);
public static bool CheckDirectoryEmpty_Fast(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException(path);
}
if (Directory.Exists(path))
{
if (path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path += "*";
else
path += Path.DirectorySeparatorChar + "*";
WIN32_FIND_DATA findData;
var findHandle = FindFirstFile(path, out findData);
if (findHandle != INVALID_HANDLE_VALUE)
{
try
{
bool empty = true;
do
{
if (findData.cFileName != "." && findData.cFileName != "..")
empty = false;
} while (empty && FindNextFile(findHandle, out findData));
return empty;
}
finally
{
FindClose(findHandle);
}
}
throw new Exception("Failed to get directory first file",
Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
}
throw new DirectoryNotFoundException();
}
将来、誰かの役に立つことを願っています。
関連
-
[解決済み] .net の OOM 問題を解決する必要があります。
-
[解決済み] Linuxで特定のテキストを含むすべてのファイルを検索するにはどうすればよいですか?
-
[解決済み] Bashスクリプトのソースディレクトリをスクリプト自体から取得するにはどうすればよいですか?
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] enumを列挙するには
-
[解決済み] Pythonでファイルやフォルダを削除する方法は?
-
[解決済み] .NETでのdecimal, float, doubleの違い?
-
[解決済み] フォルダとそのサブフォルダ/ファイルのパーミッションを一括で変更する方法
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Git リポジトリに空のディレクトリを追加するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンパイラーエラーメッセージ。コンパイラはエラーコード -532462766 で失敗しました。
-
[解決済み] app.configのマッピングがないアセンブリのapp.configの再マッピングを考慮する。
-
[解決済み] 16進数値0x00は無効な文字です。
-
[解決済み] ファイルまたはアセンブリ 'System.Data.SQLite' をロードできませんでした。
-
[解決済み] SQL Server Compact EditionデータベースのLINQ to SQLで、"Row not found or changed "例外を解決するにはどうすればよいですか?
-
[解決済み] VB.NETで線を引く方法
-
[解決済み] ネットワークの位置からアセンブリをロードすることはできません
-
[解決済み] gacutil.exeはどこですか?
-
[解決済み] LINQ: フィルタリング基準で SingleOrDefault と FirstOrDefault() を使用する場合
-
[解決済み] .NET WebRequestを使用してsharepointにファイルをアップロードすると、409/Conflict HTTPエラーが発生する理由?