/ / .Net: Jak sprawdzić nielegalne znaki na ścieżce? - .net, ścieżka, nielegalne znaki

.Net: Jak sprawdzić nielegalne znaki na ścieżce? - .net, ścieżka, nielegalne znaki

Czy istnieje sposób sprawdzenia, czy ciąg znaków ma na celuścieżka ma nieprawidłowe znaki w .Net? Wiem, że mógłbym iterować nad każdą postacią w Path.InvalidPathChars, aby sprawdzić, czy mój String zawiera jeden, ale wolałbym proste, może bardziej formalne rozwiązanie.

Czy jest jeden?

Odkryłem, że wciąż mam wyjątek, jeśli sprawdzam tylko w Get

Aktualizacja:

Znalazłem GetInvalidPathChars nie obejmujekażda nieprawidłowa ścieżka. GetInvalidFileNameChars ma 5 kolejnych, w tym "?", Z którymi się zetknąłem. Zamierzam to zmienić, i zgłoszę, jeśli to również okaże się niewystarczające.

Aktualizacja 2:

GetInvalidFileNameChars zdecydowanie nie jest tym, co jachcieć. Zawiera ":", którą będzie zawierała absolutna ścieżka ("C: cokolwiek"). Myślę, że po prostu będę musiał użyć GetInvalidPathChars i dodać "?" I inne postacie, które powodują problemy, gdy pojawią się. Lepsze rozwiązania są mile widziane.

Odpowiedzi:

36 dla odpowiedzi nr 1

InvalidPathChars jest przestarzałe. Zamiast tego należy użyć GetInvalidPathChars ():

    public static bool FilePathHasInvalidChars(string path)
{

return (!string.IsNullOrEmpty(path) && path.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0);
}

Edycja: Nieco dłuższe, ale obsługuje ścieżkę w stosunku do nieprawidłowych plików w jednej funkcji:

    // WARNING: Not tested
public static bool FilePathHasInvalidChars(string path)
{
bool ret = false;
if(!string.IsNullOrEmpty(path))
{
try
{
// Careful!
//    Path.GetDirectoryName("C:DirectorySubDirectory")
//    returns "C:Directory", which may not be what you want in
//    this case. You may need to explicitly add a trailing 
//    if path is a directory and not a file path. As written,
//    this function just assumes path is a file path.
string fileName = System.IO.Path.GetFileName(path);
string fileDirectory = System.IO.Path.GetDirectoryName(path);

// we don"t need to do anything else,
// if we got here without throwing an
// exception, then the path does not
// contain invalid characters
}
catch (ArgumentException)
{
// Path functions will throw this
// if path contains invalid chars
ret = true;
}
}
return ret;
}

4 dla odpowiedzi nr 2

Zachowaj ostrożność, polegając na Path.GetInvalidFileNameChars, które mogą nie być tak niezawodne, jak myślisz, zwróć uwagę na następującą uwagę w dokumentacji MSDN na Path.GetInvalidFileNameChars:

Tablica zwrócona z tej metody to nie może zawierać pełnego zestawu znaków, które są nieprawidłowe w nazwach plików i katalogów. Pełny zestaw nieprawidłowych znaków może się różnićsystem plików. Na przykład na platformach komputerowych opartych na systemie Windows niepoprawne znaki ścieżki mogą zawierać znaki ASCII / Unicode od 1 do 31, a także cytat ("), mniej niż (<), większy niż (>), potok (|), backspace ( b), null (

To nie jest lepsze z Path.GetInvalidPathChars metoda. Zawiera dokładnie tę samą uwagę.


2 dla odpowiedzi nr 3

Prawdopodobnie dla ciebie jest za późno, ale może pomóc komuś innemu. Zmierzyłem się z tym samym problemem i potrzebowałem znaleźć niezawodny sposób na oczyszczenie ścieżki.

Oto czego użyłem w 3 krokach:

Krok 1: Niestandardowe czyszczenie.

public static string RemoveSpecialCharactersUsingCustomMethod(this string expression, bool removeSpecialLettersHavingASign = true)
{
var newCharacterWithSpace = " ";
var newCharacter = "";

// Return carriage handling
// ASCII LINE-FEED character (LF),
expression = expression.Replace("n", newCharacterWithSpace);
// ASCII CARRIAGE-RETURN character (CR)
expression = expression.Replace("r", newCharacterWithSpace);

// less than : used to redirect input, allowed in Unix filenames, see Note 1
expression = expression.Replace(@"<", newCharacter);
// greater than : used to redirect output, allowed in Unix filenames, see Note 1
expression = expression.Replace(@">", newCharacter);
// colon: used to determine the mount point / drive on Windows;
// used to determine the virtual device or physical device such as a drive on AmigaOS, RT-11 and VMS;
// used as a pathname separator in classic Mac OS. Doubled after a name on VMS,
// indicates the DECnet nodename (equivalent to a NetBIOS (Windows networking) hostname preceded by "\".).
// Colon is also used in Windows to separate an alternative data stream from the main file.
expression = expression.Replace(@":", newCharacter);
// quote : used to mark beginning and end of filenames containing spaces in Windows, see Note 1
expression = expression.Replace(@"""", newCharacter);
// slash : used as a path name component separator in Unix-like, Windows, and Amiga systems.
// (The MS-DOS command.com shell would consume it as a switch character, but Windows itself always accepts it as a separator.[16][vague])
expression = expression.Replace(@"/", newCharacter);
// backslash : Also used as a path name component separator in MS-DOS, OS/2 and Windows (where there are few differences between slash and backslash); allowed in Unix filenames, see Note 1
expression = expression.Replace(@"", newCharacter);
// vertical bar or pipe : designates software pipelining in Unix and Windows; allowed in Unix filenames, see Note 1
expression = expression.Replace(@"|", newCharacter);
// question mark : used as a wildcard in Unix, Windows and AmigaOS; marks a single character. Allowed in Unix filenames, see Note 1
expression = expression.Replace(@"?", newCharacter);
expression = expression.Replace(@"!", newCharacter);
// asterisk or star : used as a wildcard in Unix, MS-DOS, RT-11, VMS and Windows. Marks any sequence of characters
// (Unix, Windows, later versions of MS-DOS) or any sequence of characters in either the basename or extension
// (thus "*.*" in early versions of MS-DOS means "all files". Allowed in Unix filenames, see note 1
expression = expression.Replace(@"*", newCharacter);
// percent : used as a wildcard in RT-11; marks a single character.
expression = expression.Replace(@"%", newCharacter);
// period or dot : allowed but the last occurrence will be interpreted to be the extension separator in VMS, MS-DOS and Windows.
// In other OSes, usually considered as part of the filename, and more than one period (full stop) may be allowed.
// In Unix, a leading period means the file or folder is normally hidden.
expression = expression.Replace(@".", newCharacter);
// space : allowed (apart MS-DOS) but the space is also used as a parameter separator in command line applications.
// This can be solved by quoting, but typing quotes around the name every time is inconvenient.
//expression = expression.Replace(@"%", " ");
expression = expression.Replace(@"  ", newCharacter);

if (removeSpecialLettersHavingASign)
{
// Because then issues to zip
// More at : http://www.thesauruslex.com/typo/eng/enghtml.htm
expression = expression.Replace(@"ê", "e");
expression = expression.Replace(@"ë", "e");
expression = expression.Replace(@"ï", "i");
expression = expression.Replace(@"œ", "oe");
}

return expression;
}

Krok 2: Sprawdź wszystkie nieprawidłowe znaki, które nie zostały jeszcze usunięte.

Dodatkowy krok weryfikacyjny, używam Path.GetInvalidPathChars() metoda zamieszczona powyżej, aby wykryć potencjalne nieprawidłowe znaki, które nie zostały jeszcze usunięte.

public static bool ContainsAnyInvalidCharacters(this string path)
{
return (!string.IsNullOrEmpty(path) && path.IndexOfAny(Path.GetInvalidPathChars()) >= 0);
}

Krok 3: Wyczyść wszelkie znaki specjalne wykryte w kroku 2.

I na koniec, używam tej metody jako ostatniego kroku do czyszczenia wszystkiego. (z Jak usunąć niedozwolone znaki ze ścieżki i nazw plików?):

public static string RemoveSpecialCharactersUsingFrameworkMethod(this string path)
{
return Path.GetInvalidFileNameChars().Aggregate(path, (current, c) => current.Replace(c.ToString(), string.Empty));
}

Loguję dowolny nieprawidłowy znak, który nie został wyczyszczony w pierwszym kroku. Wybieram, aby przejść w ten sposób, aby poprawić moją niestandardową metodę, gdy tylko zostanie wykryty "wyciek". Nie mogę polegać na Path.GetInvalidFileNameChars() z powodu następującego oświadczenia a zgłoszonego powyżej (z MSDN):

"Tablica zwrócona przez tę metodę nie może zawierać znaku kompletny zestaw znaków, które są nieprawidłowe w pliku i katalogu nazwy. "

Być może nie jest to idealne rozwiązanie, ale biorąc pod uwagę kontekst mojej aplikacji i wymagany poziom niezawodności, jest to najlepsze rozwiązanie, jakie znalazłem.


1 dla odpowiedzi nr 4

Skończyłem na pożyczaniu i łączeniu kilku wewnętrznych implementacji .NET, aby wymyślić metodę performance:

/// <summary>Determines if the path contains invalid characters.</summary>
/// <remarks>This method is intended to prevent ArgumentException"s from being thrown when creating a new FileInfo on a file path with invalid characters.</remarks>
/// <param name="filePath">File path.</param>
/// <returns>True if file path contains invalid characters.</returns>
private static bool ContainsInvalidPathCharacters(string filePath)
{
for (var i = 0; i < filePath.Length; i++)
{
int c = filePath[i];

if (c == """ || c == "<" || c == ">" || c == "|" || c == "*" || c == "?" || c < 32)
return true;
}

return false;
}

Użyłem go w ten sposób, ale również zawinąłem w bloku try / catch dla bezpieczeństwa:

if ( !string.IsNullOrWhiteSpace(path) && !ContainsInvalidPathCharacters(path))
{
FileInfo fileInfo = null;

try
{
fileInfo = new FileInfo(path);
}
catch (ArgumentException)
{
}

...
}

0 dla odpowiedzi № 5

Zbyt późno, ale jeśli zadaniem jest sprawdzenie, czy użytkownik wprowadził coś ważnego jako ścieżkę, istnieje połączone rozwiązanie dla ścieżek.

Path.GetInvalidFileNameChars() zwraca listę znaków niedozwolonych dla pliku, ale katalog podąża za regułami pliku z wyjątkiem separatorów (które mogliśmy uzyskać z systemu) i specyfikatora głównego (C:, możemy po prostu usunąć go z wyszukiwania). Tak, Path.GetInvalidFileNameChars() zwraca nie kompletny zestaw, ale jest lepszy niż spróbuj znaleźć wszystkie ręcznie.

Więc:

private static bool CheckInvalidPath(string targetDir)
{
string root;
try
{
root = Path.GetPathRoot(targetDir);
}
catch
{
// the path is definitely invalid if it has crashed
return false;
}

// of course it is better to cache it as it creates
// new array on each call
char[] chars = Path.GetInvalidFileNameChars();

// ignore root
for (int i = root.Length; i < targetDir.Length; i++)
{
char c = targetDir[i];

// separators are allowed
if (c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar)
continue;

// check for illegal chars
for (int j = 0; j < chars.Length; j++)
if (c == chars[j])
return false;
}

return true;
}

Odkryłem, że metody takie jak Path.GetFileName nie zawiesza się dla ścieżek takich jak C:* (co jest całkowicie nieważne) i nawet kontrola oparta na wyjątkach nie jest wystarczająca. Jedyne, co spowoduje awarię Path.GetPathRoot jest nieprawidłowym rootem (np CC:someDir). Więc wszystko inne powinno być zrobione ręcznie.