ver vacias vacia tiene recuperar puedo pero muestra movil mis memorias memoria los llenas llena estan esta conectar carpetas carpeta archivos aparece .net io folder

.net - tiene - recuperar archivos de carpetas vacias en memorias usb



¿Cómo verificar rápidamente si la carpeta está vacía(.NET)? (17)

Tengo que verificar si el directorio en el disco está vacío. Significa que no contiene ninguna carpeta / archivo. Lo sé, que hay un método simple. Obtenemos una matriz de FileSystemInfo y verificamos si el recuento de elementos equivale a cero. Algo como eso:

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(); }

Este enfoque parece estar bien. ¡¡PERO!! Es muy, muy malo desde una perspectiva de rendimiento. GetFileSystemInfos () es un método muy difícil. En realidad, enumera todos los objetos del sistema de archivos de la carpeta, obtiene todas sus propiedades, crea objetos, rellena la matriz tipada, etc. Y todo esto simplemente para verificar Longitud. Eso es estúpido, ¿no?

Acabo de perfilar dicho código y determiné que ~ 250 llamadas de dicho método se ejecutan en ~ 500 ms. Esto es muy lento y creo que es posible hacerlo mucho más rápido.

¿Alguna sugerencia?


Aquí está la solución extra rápida, que finalmente implementé. Aquí estoy usando WinAPI y funciones FindFirstFile , FindNextFile . Permite evitar la enumeración de todos los elementos en la carpeta y se detiene justo después de detectar el primer objeto en la carpeta . Este enfoque es ~ 6 (!!) veces más rápido que el descrito anteriormente. ¡250 llamadas en 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(); }

Espero que sea útil para alguien en el futuro.


Aquí hay algo que podría ayudarte a hacerlo. Logré hacerlo en dos iteraciones.

private static IEnumerable<string> GetAllNonEmptyDirectories(string path) { var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.AllDirectories) .ToList(); var directoryList = (from directory in directories let isEmpty = Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories).Length == 0 where !isEmpty select directory) .ToList(); return directoryList.ToList(); }


En algún momento, es posible que desee verificar si existen archivos dentro de los subdirectorios e ignorar esos subdirectorios vacíos; En este caso, puede utilizar el método a continuación:

public bool isDirectoryContainFiles(string path) { if (!Directory.Exists(path)) return false; return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any(); }


En cualquier caso, tendrá que ir al disco duro para obtener esta información, y solo esto prevalecerá sobre cualquier creación de objeto y relleno de matriz.


Estoy seguro de que las otras respuestas son más rápidas, y tu pregunta fue si una carpeta contenía o no archivos o carpetas ... pero creo que la mayoría de las personas considerarían un directorio vacío si no contiene ningún archivo. es decir, todavía está "vacío" para mí si contiene subdirectorios vacíos ... esto puede no ser apto para su uso, ¡pero puede serlo para otros!

public bool DirectoryIsEmpty(string path) { int fileCount = Directory.GetFiles(path).Length; if (fileCount > 0) { return false; } string[] dirs = Directory.GetDirectories(path); foreach (string dir in dirs) { if (! DirectoryIsEmpty(dir)) { return false; } } return true; }


Fácil y simple:

int num = Directory.GetFiles(pathName).Length; if (num == 0) { //empty }


Gracias, a todos, por las respuestas. Traté de usar los métodos Directory.GetFiles () y Directory.GetDirectories () . ¡Buenas noticias! ¡El rendimiento mejoró dos veces! 229 llamadas en 221ms. Pero también espero que sea posible evitar la enumeración de todos los elementos en la carpeta. De acuerdo, todavía se está ejecutando el trabajo innecesario. ¿No lo crees?

Después de todas las investigaciones, llegué a una conclusión, que en .NET puro, la optimización adicional es imposible. Voy a jugar con la función FindFirstFile de WinAPI. Espero que ayude


Hay una nueva característica en Directory and DirectoryInfo en .NET 4 que permite devolver un IEnumerable en lugar de una matriz, y comienza a devolver los resultados antes de leer todos los contenidos del directorio.

Mira aquí y there

public bool IsDirectoryEmpty(string path) { IEnumerable<string> items = Directory.EnumerateFileSystemEntries(path); using (IEnumerator<string> en = items.GetEnumerator()) { return !en.MoveNext(); } }

EDITAR: viendo esa respuesta de nuevo, me doy cuenta de que este código se puede hacer mucho más simple ...

public bool IsDirectoryEmpty(string path) { return !Directory.EnumerateFileSystemEntries(path).Any(); }


Lo uso para carpetas y archivos (no sé si es óptimo)

if(Directory.GetFileSystemEntries(path).Length == 0)


Mi código es increíble, solo tomó 00: 00: 00.0007143 menos de milisegundos con 34 archivos en la carpeta

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); bool IsEmptyDirectory = (Directory.GetFiles("d://pdf").Length == 0); sw.Stop(); Console.WriteLine(sw.Elapsed);


No conozco un método que le indique sucintamente si una carpeta determinada contiene otras carpetas o archivos, sin embargo, usando:

Directory.GetFiles(path); & Directory.GetDirectories(path);

debería ayudar al rendimiento ya que ambos métodos solo devolverán una matriz de cadenas con los nombres de los archivos / directorios en lugar de los objetos completos FileSystemInfo.


No sé sobre las estadísticas de rendimiento en este caso, pero ¿ha intentado utilizar el método estático Directory.GetFiles() ?

Devuelve una matriz de cadenas que contiene nombres de archivos (no FileInfos) y puede verificar la longitud de la matriz de la misma manera que arriba.


Puede probar Directory.Exists(path) y Directory.GetFiles(path) - probablemente menos sobrecarga (sin objetos, solo cadenas, etc.).


Si no te importa dejar C # puro y aceptar llamadas de WinApi , entonces quizás quieras considerar la función PathIsDirectoryEmpty() . De acuerdo con MSDN, la función:

Devuelve TRUE si pszPath es un directorio vacío. Devuelve FALSE si pszPath no es un directorio, o si contiene al menos un archivo que no sea "." o "..."

Esa parece ser una función que hace exactamente lo que quieres, por lo que probablemente esté bien optimizada para esa tarea (aunque no he probado eso).

Para llamarlo desde C #, el sitio de pinvoke.net debería ayudarlo. (Desafortunadamente, aún no describe esta función determinada, pero debería poder encontrar algunas funciones con argumentos similares y tipo de retorno allí y usarlas como base para su llamada. Si vuelve a mirar el MSDN, dice que la DLL para importar es shlwapi.dll )


También debe ajustar su prueba en un bloque try / catch para asegurarse de que maneja adecuadamente una excepción DirectoryNotFoundException. Esta es una condición de carrera clásica en caso de que la carpeta se elimine inmediatamente después de haber comprobado si existía.


Utilizar esta. Es sencillo.

Public Function IsDirectoryEmpty(ByVal strDirectoryPath As String) As Boolean Dim s() As String = _ Directory.GetFiles(strDirectoryPath) If s.Length = 0 Then Return True Else Return False End If End Function


private static void test() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); string [] dirs = System.IO.Directory.GetDirectories("C://Test//"); string[] files = System.IO.Directory.GetFiles("C://Test//"); if (dirs.Length == 0 && files.Length == 0) Console.WriteLine("Empty"); else Console.WriteLine("Not Empty"); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); }

Esta prueba rápida volvió en 2 milisegundos para la carpeta cuando está vacía y cuando contiene subcarpetas y archivos (5 carpetas con 5 archivos en cada una)