Próbuję użyć tej Directory.GetFiles()
metody do pobrania listy plików wielu typów, takich jak mp3
„s jpg
” i „s”. Próbowałem obu z poniższych bez powodzenia:
Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
Czy można to zrobić za jednym razem?
c#
filesystems
.net
Jason Z
źródło
źródło
Odpowiedzi:
W przypadku .NET 4.0 i nowszych wersji
W przypadku wcześniejszych wersji .NET
edycja: Proszę przeczytać komentarze. Poprawa, którą sugeruje Paul Farry , oraz problem pamięci / wydajności, na który wskazuje Christian.K , są bardzo ważne.
źródło
s.ToLower().Endswith...
s.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Directory.GetFiles
zDirectory.EnumerateFiles
, msdn.microsoft.com/en-us/library/dd383571.aspx , co pozwoli uniknąć problemów z pamięcią, że @ Christian.K wspomina.Co powiesz na to:
Znalazłem to tutaj (w komentarzach): http://msdn.microsoft.com/en-us/library/wz42302f.aspx
źródło
Parallel.ForEach
aby uzyskać je równolegleJeśli masz dużą listę rozszerzeń do sprawdzenia, możesz użyć następujących. Nie chciałem tworzyć wielu instrukcji OR, więc zmodyfikowałem to, co napisał Lette.
źródło
Path.GetExtension
zwraca „.ext”, a nie „* .ext” (przynajmniej w wersji 3.5+)..abc
, a obsługiwane rozszerzenie zawiera.abcd
. Będzie pasować, choć nie powinno. Aby naprawić: zasupportedExtensions = ".jpg|.abcd|";
pomocą.Contains(Path.GetExtension(s).ToLower() + "|")
. Oznacza to, że w teście umieść znak separatora. WAŻNE: znak separatora musi także znajdować się po POSTANOWIU w obsługiwanych wyjątkach.dla
Mógłbyś:
Directory.EnumerateFiles
celu zwiększenia wydajności ( jaka jest różnica między Directory.EnumerateFiles a Directory.GetFiles? ).EndsWith("aspx", StringComparison.OrdinalIgnoreCase)
zamiast.ToLower().EndsWith("aspx")
)Ale prawdziwa korzyść
EnumerateFiles
pojawia się po podzieleniu filtrów i scaleniu wyników:Robi się trochę szybciej, jeśli nie musisz zamieniać ich w globusy (tj.
exts = new[] {"*.mp3", "*.jpg"}
Już).Ocena wydajności na podstawie następującego testu LinqPad (uwaga:
Perf
wystarczy powtórzyć delegata 10000 razy) https://gist.github.com/zaus/7454021(przesłany i rozszerzony z „duplikatu”, ponieważ to pytanie wyraźnie nie wymagało LINQ: Wiele rozszerzeń plików searchPattern dla System.IO.Directory.GetFiles )
źródło
.FilterFiles(path, "jpg", "gif")
) jest lepsze niż „jawne globusy” (tj.FilterFiles(path, "*.jpg", "*.gif")
.).Wiem, że to stare pytanie, ale LINQ: (.NET40 +)
źródło
file.ToLower()
łatwego dopasowania do wielkich liter. A może najpierw wyodrębnisz rozszerzenie, aby Regex nie musiał sprawdzać całej ścieżki:Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
Istnieje również rozwiązanie opadania, które wydaje się nie mieć narzutu pamięci ani wydajności i jest dość eleganckie:
źródło
Kolejny sposób korzystania z Linq, ale bez konieczności zwracania wszystkiego i filtrowania tego w pamięci.
W rzeczywistości są to 2 wezwania do
GetFiles()
, ale myślę, że jest to zgodne z duchem pytania i zwraca je w jednym wyliczeniu.źródło
Nie. Spróbuj wykonać następujące czynności:
Pobrano z: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx
źródło
Pozwolić
Następnie
lub
źródło
Nie mogę użyć
.Where
metody, ponieważ programuję w .NET Framework 2.0 (Linq jest obsługiwany tylko w .NET Framework 3.5+).Poniższy kod nie rozróżnia wielkości liter (tak
.CaB
lub też.cab
będzie wymieniony).źródło
Poniższa funkcja wyszukuje wiele wzorów oddzielonych przecinkami. Możesz także określić wykluczenie, np .: „! Web.config” wyszuka wszystkie pliki i wykluczy „web.config”. Wzory można mieszać.
Stosowanie:
źródło
źródło
file.Extension.ToLower()
jest złą praktyką.String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
w .NET 2.0 (bez Linq):
Następnie użyj go:
źródło
źródło
Właśnie znalazłem inny sposób, aby to zrobić. Nadal nie jedna operacja, ale wyrzucenie jej, aby zobaczyć, co myślą o niej inni ludzie.
źródło
Co powiesz na
źródło
Utwórz rozszerzenia, które mają mieć jeden ciąg, tj. „.Mp3.jpg.wma.wmf”, a następnie sprawdź, czy każdy plik zawiera odpowiednie rozszerzenie. Działa to z .net 2.0, ponieważ nie używa LINQ.
Zaletą tego podejścia jest to, że możesz dodawać lub usuwać rozszerzenia bez edycji kodu, tj. Aby dodać obrazy png, po prostu napisz myExtensions = ". Jpg.mp3.png".
źródło
s
źródło
Nie ... Uważam, że musisz wykonać tyle połączeń, ile chcesz typów plików.
Sam stworzyłbym funkcję, biorąc tablicę na ciągi znaków z potrzebnymi rozszerzeniami, a następnie iterowałem tę tablicę, wykonując wszystkie niezbędne wywołania. Ta funkcja zwróci ogólną listę plików pasujących do rozszerzeń, które wysłałem.
Mam nadzieję, że to pomoże.
źródło
Miałem ten sam problem i nie mogłem znaleźć właściwego rozwiązania, więc napisałem funkcję o nazwie GetFiles:
Ta funkcja zadzwoni
Directory.Getfiles()
tylko raz.Na przykład wywołaj taką funkcję:
EDYCJA: Aby uzyskać jeden plik z wieloma rozszerzeniami, użyj tego:
Na przykład wywołaj taką funkcję:
źródło
Zastanawiam się, dlaczego opublikowano tak wiele „rozwiązań”?
Jeśli moje zrozumienie dla początkujących, jak działa GetFiles, jest słuszne, istnieją tylko dwie opcje i każde z powyższych rozwiązań można sprowadzić do następujących:
GetFiles, a następnie filtruj: Szybko, ale zabójca pamięci z powodu przechowywania narzutu do momentu zastosowania filtrów
Filtruj podczas GetFiles: Im wolniej, tym więcej filtrów jest ustawionych, ale niskie zużycie pamięci, ponieważ nie jest przechowywany żaden narzut.
Jest to wyjaśnione w jednym z powyższych postów z imponującym testem porównawczym: Każda opcja filtru powoduje oddzielną operację GetFile, dzięki czemu ta sama część dysku twardego jest czytana kilka razy.
Moim zdaniem opcja 1) jest lepsza, ale użycie SearchOption.AllDirectories w folderach takich jak C: \ zużyłoby ogromne ilości pamięci.
Dlatego właśnie stworzyłbym rekursywną pod-metodę, która przechodzi przez wszystkie podfoldery przy użyciu opcji 1)
Powinno to spowodować tylko 1 operację GetFiles na każdym folderze i dlatego powinno być szybkie (Opcja 1), ale zużywać tylko niewielką ilość pamięci, ponieważ filtry są stosowane po odczytaniu każdego podfoldera -> obciążenie jest usuwane po każdym podfolderze.
Proszę, popraw mnie jeśli się mylę. Jestem, jak powiedziałem, całkiem nowy w programowaniu, ale chcę uzyskać głębsze zrozumienie rzeczy, aby ostatecznie stać się w tym dobry :)
źródło
Jeśli używasz VB.NET (lub zaimportowałeś zależność do swojego projektu w C #), faktycznie istnieje metoda wygody, która pozwala na filtrowanie wielu rozszerzeń:
W VB.NET można uzyskać do niego dostęp poprzez przestrzeń nazw My:
Niestety te metody wygody nie obsługują leniwie ocenianego wariantu
Directory.EnumerateFiles()
.źródło
nie wiem, które rozwiązanie jest lepsze, ale używam tego:
źródło
Oto prosty i elegancki sposób na uzyskanie odfiltrowanych plików
źródło
Lub możesz po prostu przekonwertować ciąg rozszerzeń na Ciąg ^
źródło
Używanie wzorca wyszukiwania GetFiles do filtrowania rozszerzenia nie jest bezpieczne !! Na przykład masz dwa pliki Test1.xls i Test2.xlsx i chcesz odfiltrować plik xls za pomocą wzorca wyszukiwania * .xls, ale GetFiles zwraca oba Test1.xls i Test2.xlsx Nie wiedziałem o tym i wystąpił błąd w produkcji środowisko, gdy niektóre pliki tymczasowe nagle zostały potraktowane jako odpowiednie pliki. Wzorzec wyszukiwania to * .txt, a pliki tymczasowe nazwano * .txt20181028_100753898 Aby wzorzec wyszukiwania nie mógł być zaufany, należy dodatkowo sprawdzić nazwy plików.
źródło