Saya harus memeriksa, apakah direktori pada disk kosong. Artinya, tidak mengandung folder / file apa pun. Saya tahu, bahwa ada metode sederhana. Kami mendapatkan larik FileSystemInfo dan memeriksa apakah jumlah elemen sama dengan nol. Sesuatu seperti itu:
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();
}
Pendekatan ini tampaknya baik-baik saja. TAPI!! Ini sangat, sangat buruk dari perspektif kinerja. GetFileSystemInfos () adalah metode yang sangat sulit. Sebenarnya, ia menghitung semua objek filesystem folder, mendapatkan semua propertinya, membuat objek, mengisi array yang diketik, dll. Dan semua ini hanya dengan cukup memeriksa Panjang. Itu bodoh, bukan?
Saya baru saja membuat profil kode seperti itu dan memutuskan, bahwa ~ 250 panggilan metode seperti itu dieksekusi dalam ~ 500ms. Ini sangat lambat dan saya percaya, adalah mungkin untuk melakukannya lebih cepat.
Ada saran?
Jawaban:
Ada fitur baru di dalam
Directory
danDirectoryInfo
.NET 4 yang memungkinkan mereka untuk mengembalikanIEnumerable
bukan array, dan mulai mengembalikan hasil sebelum membaca semua konten direktori.Directory.EnumerateFileSystemEntries
metode kelebihan bebanEDIT: melihat jawaban itu lagi, saya menyadari kode ini dapat dibuat lebih sederhana ...
sumber
EnumerateFileSystemEntries
, atau menggunakan.Any(condition)
(tentukan kondisi sebagai ekspresi lambda, atau sebagai metode yang mengambil jalur sebagai parameter).return !items.GetEnumerator().MoveNext();
Inilah solusi ekstra cepat, yang akhirnya saya terapkan. Di sini saya menggunakan WinAPI dan fungsi FindFirstFile , FindNextFile . Hal ini memungkinkan untuk menghindari penghitungan semua item di Folder dan berhenti tepat setelah mendeteksi objek pertama di Folder . Pendekatan ini ~ 6 (!!) kali lebih cepat, daripada yang dijelaskan di atas. 250 panggilan dalam 36ms!
Saya berharap ini akan bermanfaat bagi seseorang di masa depan.
sumber
SetLastError = true
keDllImport
untukFindFirstFile
agarMarshal.GetHRForLastWin32Error()
panggilan berfungsi dengan benar, seperti yang dijelaskan di bagian Keterangan pada dokumen MSDN untuk GetHRForLastWin32Error () .Anda dapat mencoba
Directory.Exists(path)
danDirectory.GetFiles(path)
- mungkin lebih sedikit overhead (tidak ada objek - hanya string dll).sumber
Tes cepat ini kembali dalam 2 milidetik untuk folder saat kosong dan ketika berisi subfolder & file (masing-masing 5 folder dengan 5 file)
sumber
Saya menggunakan ini untuk folder dan file (tidak tahu apakah itu optimal)
sumber
Jika Anda tidak keberatan meninggalkan C # murni dan pergi untuk panggilan WinApi , maka Anda mungkin ingin mempertimbangkan fungsi PathIsDirectoryEmpty () . Menurut MSDN, fungsinya:
Tampaknya itu adalah fungsi yang melakukan apa yang Anda inginkan, jadi mungkin dioptimalkan dengan baik untuk tugas itu (walaupun saya belum mengujinya).
Untuk memanggilnya dari C #, situs pinvoke.net akan membantu Anda. (Sayangnya, ini belum menggambarkan fungsi tertentu ini, tetapi Anda harus dapat menemukan beberapa fungsi dengan argumen yang sama dan kembali ketik di sana dan menggunakannya sebagai dasar untuk panggilan Anda. Jika Anda melihat lagi ke dalam MSDN, dikatakan bahwa DLL untuk mengimpor dari is
shlwapi.dll
)sumber
Saya tidak tahu tentang statistik kinerja yang satu ini, tetapi apakah Anda sudah mencoba menggunakan
Directory.GetFiles()
metode statis?Ini mengembalikan array string yang berisi nama file (bukan FileInfos) dan Anda dapat memeriksa panjang array dengan cara yang sama seperti di atas.
sumber
Saya yakin jawaban lain lebih cepat, dan pertanyaan Anda menanyakan apakah folder berisi file atau folder ... tapi saya pikir sebagian besar waktu orang akan menganggap direktori kosong jika tidak mengandung file. yaitu masih "kosong" bagi saya jika berisi subdirektori kosong ... ini mungkin tidak cocok untuk penggunaan Anda, tetapi mungkin untuk orang lain!
sumber
Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any()
Anda harus pergi ke hard drive untuk informasi ini, dan ini saja akan mengalahkan pembuatan objek dan mengisi array.
sumber
Saya tidak mengetahui metode yang secara ringkas akan memberi tahu Anda jika folder yang diberikan berisi folder atau file lain, menggunakan:
seharusnya membantu kinerja karena kedua metode ini hanya akan mengembalikan array string dengan nama file / direktori daripada seluruh objek FileSystemInfo.
sumber
Terima kasih, semuanya, untuk balasan. Saya mencoba menggunakan metode Directory.GetFiles () dan Directory.GetDirectories () . Kabar baik! Kinerja meningkat ~ dua kali lipat! 229 panggilan dalam 221ms. Tetapi saya juga berharap, bahwa mungkin untuk menghindari penghitungan semua item dalam folder. Setuju, bahwa masih pekerjaan yang tidak perlu dijalankan. Bukankah begitu?
Setelah semua investigasi, saya mencapai kesimpulan, bahwa di bawah. NET optimisasi lebih lanjut tidak mungkin. Saya akan bermain dengan fungsi FindFirstFile WinAPI . Semoga ini bisa membantu.
sumber
Beberapa waktu Anda mungkin ingin memverifikasi apakah ada file di dalam sub direktori dan mengabaikan sub direktori kosong tersebut; dalam hal ini Anda dapat menggunakan metode di bawah ini:
sumber
Mudah dan sederhana:
sumber
Berbasis di kode Brad Parks :
sumber
Kode saya luar biasa hanya butuh 00: 00: 00.0007143 kurang dari milidetik dengan 34 file di folder
sumber
Ini ada sesuatu yang mungkin bisa membantu Anda melakukannya. Saya berhasil melakukannya dalam dua iterasi.
sumber
Karena Anda akan bekerja dengan objek DirectoryInfo, saya akan pergi dengan ekstensi
sumber
Gunakan ini. Itu mudah.
sumber