Eu tenho que verificar, se o diretório no disco está vazio. Isso significa que ele não contém nenhuma pasta / arquivo. Eu sei que existe um método simples. Obtemos uma matriz de FileSystemInfo e verificamos se a contagem de elementos é igual a zero. Algo parecido:
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();
}
Essa abordagem parece bem. MAS!! É muito, muito ruim do ponto de vista do desempenho. GetFileSystemInfos () é um método muito difícil. Na verdade, ele enumera todos os objetos do sistema de arquivos da pasta, obtém todas as suas propriedades, cria objetos, preenche a matriz digitada, etc. E tudo isso apenas para verificar Comprimento. Isso é estúpido, não é?
Acabei de criar um perfil desse código e determinei que ~ 250 chamadas desse método são executadas em ~ 500ms. Isso é muito lento e acredito que é possível fazê-lo muito mais rápido.
Alguma sugestão?
Respostas:
Há um novo recurso no
Directory
eDirectoryInfo
no .NET 4, que lhes permite retornar umaIEnumerable
vez de uma matriz, e começar a retornar resultados antes de ler todo o conteúdo do diretório.Directory.EnumerateFileSystemEntries
sobrecargas de métodoEDIT: vendo essa resposta novamente, percebo que esse código pode ser muito mais simples ...
fonte
EnumerateFileSystemEntries
ou usar.Any(condition)
(especificar a condição como uma expressão lambda ou como um método que usa um caminho como parâmetro).return !items.GetEnumerator().MoveNext();
Aqui está a solução extra rápida que eu finalmente implementei. Aqui estou usando o WinAPI e as funções FindFirstFile , FindNextFile . Permite evitar a enumeração de todos os itens da pasta e para logo após a detecção do primeiro objeto na pasta . Essa abordagem é ~ 6 (!!) vezes mais rápida do que a descrita acima. 250 chamadas em 36ms!
Espero que seja útil para alguém no futuro.
fonte
SetLastError = true
aoDllImport
paraFindFirstFile
para que aMarshal.GetHRForLastWin32Error()
chamada funcione corretamente, conforme descrito na seção Comentários do documento do MSDN para GetHRForLastWin32Error () .Você pode tentar
Directory.Exists(path)
eDirectory.GetFiles(path)
- provavelmente menos sobrecarga (sem objetos - apenas strings etc.).fonte
Esse teste rápido voltou em 2 milissegundos para a pasta quando vazia e ao conter subpastas e arquivos (5 pastas com 5 arquivos em cada)
fonte
Eu uso isso para pastas e arquivos (não sei se é o ideal)
fonte
Se você não se importa em deixar o C # puro e fazer chamadas WinApi , considere a função PathIsDirectoryEmpty () . De acordo com o MSDN, a função:
Essa parece ser uma função que faz exatamente o que você deseja, portanto provavelmente está bem otimizada para essa tarefa (embora eu não a tenha testado).
Para chamá-lo de C #, o site pinvoke.net deve ajudá-lo. (Infelizmente, ainda não descreve essa função, mas você deve encontrar algumas funções com argumentos semelhantes e retornar o tipo lá e usá-las como base para sua chamada. Se você olhar novamente para o MSDN, ele indicará que a DLL da qual importar é
shlwapi.dll
)fonte
Não conheço as estatísticas de desempenho desta, mas você já tentou usar o
Directory.GetFiles()
método estático?Ele retorna uma matriz de cadeias contendo nomes de arquivos (não FileInfos) e você pode verificar o comprimento da matriz da mesma maneira que acima.
fonte
Tenho certeza de que as outras respostas são mais rápidas e sua pergunta perguntou se uma pasta continha ou não arquivos ou pastas ... mas acho que na maioria das vezes as pessoas consideram um diretório vazio se ele não contiver arquivos. ou seja, ainda está "vazio" para mim se contiver subdiretórios vazios ... isso pode não ser adequado ao seu uso, mas pode ser para outros!
fonte
Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any()
De qualquer forma, você terá que usar o disco rígido para obter essas informações, e isso sozinho superará qualquer criação de objeto e preenchimento de matriz.
fonte
Não estou ciente de um método que informará sucintamente se uma determinada pasta contém outras pastas ou arquivos, no entanto, usando:
deve ajudar o desempenho, pois esses dois métodos retornarão apenas uma matriz de cadeias com os nomes dos arquivos / diretórios, em vez de objetos inteiros FileSystemInfo.
fonte
Obrigado a todos, pelas respostas. Tentei usar os métodos Directory.GetFiles () e Directory.GetDirectories () . Boas notícias! O desempenho melhorou ~ duas vezes! 229 chamadas em 221ms. Mas também espero que seja possível evitar a enumeração de todos os itens da pasta. Concorde que ainda o trabalho desnecessário está sendo executado. Você não acha?
Depois de todas as investigações, cheguei a uma conclusão de que, sob o .NET puro, é impossível uma otimização adicional. Vou jogar com a função FindFirstFile do WinAPI . Espero que ajude.
fonte
Algum tempo, convém verificar se existem arquivos dentro dos subdiretórios e ignorar esses subdiretórios vazios; Nesse caso, você pode usar o método abaixo:
fonte
Fácil e simples:
fonte
Baseado no código de Brad Parks :
fonte
Meu código é incrível, levou apenas 00: 00: 00.0007143 menos de milissegundo com 34 arquivos na pasta
fonte
Aqui está algo que pode ajudá-lo a fazer isso. Consegui fazer isso em duas iterações.
fonte
Como você trabalha com um objeto DirectoryInfo de qualquer maneira, eu usaria uma extensão
fonte
Usa isto. É simples.
fonte