Chcę dołączyć funkcję zmiany nazwy pliku wsadowego do mojej aplikacji. Użytkownik może wpisać wzorzec docelowej nazwy pliku i (po zastąpieniu niektórych symboli wieloznacznych we wzorcu) muszę sprawdzić, czy będzie to poprawna nazwa pliku w systemie Windows. Próbowałem użyć wyrażenia regularnego, takiego jak, [a-zA-Z0-9_]+
ale nie zawiera ono wielu znaków narodowych z różnych języków (np. Umlauty i tak dalej). Jaki jest najlepszy sposób wykonania takiej kontroli?
c#
windows
file
filesystems
tłuc
źródło
źródło
Odpowiedzi:
Możesz pobrać listę nieprawidłowych znaków z
Path.GetInvalidPathChars
iGetInvalidFileNameChars
.UPD: Zobacz sugestię Steve'a Coopera, jak używać ich w wyrażeniu regularnym.
UPD2: Należy zauważyć, że zgodnie z sekcją Uwagi w witrynie MSDN „Nie gwarantuje się, że tablica zwrócona przez tę metodę będzie zawierała pełny zestaw znaków, które są nieprawidłowe w nazwach plików i katalogów”. Odpowiedź udzielona przez sixlettervaliables zawiera więcej szczegółów.
źródło
Z artykułu „Nazywanie pliku lub katalogu” w witrynie MSDN można zapoznać się z ogólnymi konwencjami określającymi prawidłową nazwę pliku w systemie Windows:
Możesz użyć dowolnego znaku w bieżącej stronie kodowej (Unicode / ANSI powyżej 127), z wyjątkiem:
<
>
:
"
/
\
|
?
*
Kilka opcjonalnych rzeczy do sprawdzenia:
\?\
prefiksu)\?\
(należy pamiętać, że prefiks może rozszerzyć składniki katalogu i spowodować przekroczenie limitu 32 000)źródło
Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
W przypadku .Net Frameworks starszych niż 3.5 powinno to działać:
Dopasowywanie wyrażeń regularnych powinno ci pomóc. Oto fragment używający
System.IO.Path.InvalidPathChars
stałej;W przypadku .Net Frameworks po wersji 3.0 powinno to działać:
http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx
Dopasowywanie wyrażeń regularnych powinno ci pomóc. Oto fragment używający
System.IO.Path.GetInvalidPathChars()
stałej;Gdy już to wiesz, powinieneś również sprawdzić różne formaty, np.
c:\my\drive
I\\server\share\dir\file.ext
źródło
Spróbuj go użyć i wyłapuj błąd. Dozwolony zestaw może się zmieniać w różnych systemach plików lub w różnych wersjach systemu Windows. Innymi słowy, jeśli chcesz wiedzieć, czy Windows lubi tę nazwę, podaj jej nazwę i pozwól jej powiedzieć.
źródło
Ta klasa czyści nazwy plików i ścieżki; użyj go jak
Oto kod;
źródło
Oto czego używam:
Pierwszy wzorzec tworzy wyrażenie regularne zawierające nieprawidłowe / niedozwolone nazwy plików i znaki tylko dla platform Windows. Drugi robi to samo, ale zapewnia, że nazwa jest legalna dla każdej platformy.
źródło
@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
Jeden narożny przypadek, o którym należy pamiętać, który mnie zaskoczył, gdy się o tym dowiedziałem: Windows pozwala na wprowadzanie spacji w nazwach plików! Na przykład wszystkie poniższe są poprawnymi i różnymi nazwami plików w systemie Windows (bez cudzysłowów):
Jeden wniosek z tego: zachowaj ostrożność podczas pisania kodu, który odcina początkowe / końcowe białe znaki z ciągu znaków nazwy pliku.
źródło
Upraszczając odpowiedź Eugene'a Katza:
Lub
źródło
Path.GetInvalidFileNameChars
. Spójrz tutaj: referenceource.microsoft.com/#mscorlib/system/io/path.cs,289 - dla każdego twojego znakufileName
tworzony jest klon tablicy.Microsoft Windows: jądro systemu Windows zabrania używania znaków z zakresu 1-31 (tj. 0x01-0x1F) i znaków „*: <>? \ |. Chociaż system NTFS dopuszcza, aby każdy składnik ścieżki (katalog lub nazwa pliku) miał 255 znaków i o długości do około 32767 znaków, jądro Windows obsługuje tylko ścieżki o długości do 259 znaków. Dodatkowo Windows zabrania używania nazw urządzeń MS-DOS AUX, CLOCK $, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL i PRN, a także te nazwy z dowolnym rozszerzeniem (na przykład AUX.txt), z wyjątkiem używania Długie ścieżki UNC (np. \. \ C: \ nul.txt lub \? \ D: \ aux \ con). (W rzeczywistości CLOCK $ może być używany, jeśli podano rozszerzenie). Te ograniczenia dotyczą tylko systemu Windows - Na przykład Linux pozwala na użycie „*: <>? \ | nawet w NTFS.
Źródło: http://en.wikipedia.org/wiki/Filename
źródło
Zamiast jawnie uwzględniać wszystkie możliwe znaki, możesz użyć wyrażenia regularnego, aby sprawdzić obecność niedozwolonych znaków, a następnie zgłosić błąd. W idealnym przypadku aplikacja powinna nazywać pliki dokładnie tak, jak sobie tego życzy użytkownik, i płakać tylko wtedy, gdy natknie się na błąd.
źródło
Pytanie brzmi, czy próbujesz ustalić, czy nazwa ścieżki jest prawidłową ścieżką systemu Windows, czy też jest legalna w systemie, w którym działa kod. ? Myślę, że to drugie jest ważniejsze, więc osobiście prawdopodobnie zdekomponowałbym pełną ścieżkę i spróbowałbym użyć _mkdir do utworzenia katalogu, do którego należy plik, a następnie spróbuję utworzyć plik.
W ten sposób wiesz nie tylko, czy ścieżka zawiera tylko prawidłowe znaki systemu Windows, ale także czy faktycznie reprezentuje ścieżkę, którą można zapisać w tym procesie.
źródło
Używam tego, aby pozbyć się nieprawidłowych znaków w nazwach plików bez rzucania wyjątków:
źródło
Również CON, PRN, AUX, NUL, COM # i kilka innych nigdy nie są legalnymi nazwami plików w żadnym katalogu z jakimkolwiek rozszerzeniem.
źródło
Aby uzupełnić inne odpowiedzi, oto kilka dodatkowych skrajnych przypadków, które warto rozważyć.
Program Excel może mieć problemy, jeśli zapiszesz skoroszyt w pliku, którego nazwa zawiera znaki „[” lub „]”. Szczegółowe informacje można znaleźć pod adresem http://support.microsoft.com/kb/215205 .
Sharepoint ma cały dodatkowy zestaw ograniczeń. Widzieć informacje można adresem http://support.microsoft.com/kb/905231 .
źródło
W witrynie MSDN znajduje się lista niedozwolonych znaków:
źródło
Ważny jest również docelowy system plików.
W systemie NTFS niektórych plików nie można tworzyć w określonych katalogach. EG $ Uruchom w katalogu głównym
źródło
$Boot
już istnieje w katalogu?To jest już pytanie, na które udzielono już odpowiedzi, ale ze względu na „Inne opcje”, oto pytanie nie idealne:
(nie jest to idealne rozwiązanie, ponieważ używanie wyjątków jako kontroli przepływu jest ogólnie „złą rzeczą”)
źródło
true
.W tej sytuacji wyrażenia regularne są przesadą. Możesz użyć tej
String.IndexOfAny()
metody w połączeniu zPath.GetInvalidPathChars()
iPath.GetInvalidFileNameChars()
.Zauważ również, że obie
Path.GetInvalidXXX()
metody klonują wewnętrzną tablicę i zwracają clone. Więc jeśli zamierzasz robić to dużo (tysiące i tysiące razy), możesz buforować kopię nieprawidłowej tablicy znaków w celu ponownego wykorzystania.źródło
Jeśli próbujesz tylko sprawdzić, czy ciąg zawierający nazwę / ścieżkę pliku zawiera nieprawidłowe znaki, najszybszą metodą, jaką znalazłem, jest
Split()
podzielenie nazwy pliku na tablicę części, gdziekolwiek jest nieprawidłowy znak. Jeśli wynik jest tylko tablicą 1, nie ma nieprawidłowych znaków. :-)Próbowałem uruchomić tę i inne metody wymienione powyżej na nazwie pliku / ścieżki 1000000 razy w LinqPad.
Używanie
Split()
trwa tylko ~ 850 ms.Użycie
Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")
trwa około 6 sekund.Bardziej skomplikowane wyrażenia regularne są DUŻO gorzej, podobnie jak niektóre inne opcje, takie jak użycie różnych metod
Path
klasy w celu uzyskania nazwy pliku i umożliwienia ich wewnętrznej walidacji (najprawdopodobniej z powodu narzutu obsługi wyjątków).To prawda, że niezbyt często trzeba sprawdzać poprawność 1 miliona nazw plików, więc i tak pojedyncza iteracja jest odpowiednia dla większości tych metod. Ale nadal jest dość wydajny i skuteczny, jeśli szukasz tylko nieprawidłowych znaków.
źródło
wiele z tych odpowiedzi nie zadziała, jeśli nazwa pliku jest zbyt długa i działa w środowisku starszym niż Windows 10. Podobnie zastanów się, co chcesz zrobić z kropkami - zezwalanie na początkowe lub końcowe jest poprawne technicznie, ale może powodować problemy, jeśli nie chcesz, aby plik był odpowiednio trudny do zobaczenia lub usunięcia.
To jest atrybut walidacji, który utworzyłem, aby sprawdzić poprawną nazwę pliku.
i testy
źródło
Moja próba:
To nie jest idealne, ponieważ
Path.GetInvalidPathChars
nie zwraca pełnego zestawu znaków, które są nieprawidłowe w nazwach plików i katalogów, i oczywiście jest o wiele więcej subtelności.Więc używam tej metody jako uzupełnienia:
Próbuje utworzyć plik i zwrócić false, jeśli wystąpi wyjątek. Oczywiście muszę utworzyć plik, ale myślę, że to najbezpieczniejszy sposób. Należy również pamiętać, że nie usuwam utworzonych katalogów.
Możesz również użyć pierwszej metody, aby przeprowadzić podstawową walidację, a następnie ostrożnie obsłużyć wyjątki, gdy używana jest ścieżka.
źródło
Proponuję po prostu użyć Path.GetFullPath ()
źródło
Dostałem od kogoś ten pomysł. - nie wiem kto. Niech system operacyjny wykona ciężkie prace.
źródło
Ten czek
odfiltrowuje nazw z nieprawidłowych znaków (
<>:"/\|?*
i ASCII 0-31), a także zastrzeżonych urządzeń DOS (CON
,NUL
,COMx
). Pozwala na wiodące spacje i wszystkie kropki, zgodnie zPath.GetFullPath
. (Utworzenie pliku ze spacjami wiodącymi kończy się pomyślnie w moim systemie).Używany .NET Framework 4.7.1, testowany w systemie Windows 7.
źródło
Jedna linijka do weryfikacji nielegalnych znaków w ciągu:
źródło
Moim zdaniem jedyną właściwą odpowiedzią na to pytanie jest próba użycia ścieżki i pozwolenie systemowi operacyjnemu i systemowi plików na jej walidację. W przeciwnym razie po prostu ponownie zaimplementujesz (i prawdopodobnie źle) wszystkie reguły walidacji, których system operacyjny i system plików już używają, a jeśli te reguły zostaną zmienione w przyszłości, będziesz musiał zmienić kod, aby je dopasować.
źródło
Nazwy plików Windows są dość unrestrictive, tak naprawdę to nie może być nawet , że wiele kwestii. Znaki niedozwolone przez system Windows to:
Możesz łatwo napisać wyrażenie, aby sprawdzić, czy te znaki są obecne. Lepszym rozwiązaniem byłaby jednak próba nazwania plików zgodnie z życzeniem użytkownika i ostrzeganie ich, gdy nazwa pliku się nie przykleja.
źródło