Najłatwiejszy sposób sprawdzenia, czy dowolny ciąg znaków jest prawidłową nazwą pliku

79

W mojej aplikacji użytkownik może wprowadzić nazwę pliku. Przed przetwarzaniem chciałbym sprawdzić, czy ciąg wejściowy jest prawidłową nazwą pliku w systemie Windows Vista.

Jaki jest najłatwiejszy sposób na zrobienie tego?

Przez prawidłowe odnoszę się do legalnych i nieistniejących

RoflcoptrException
źródło
Kiedy mówisz poprawna nazwa pliku, czy odnosisz się do faktu, że plik istnieje, czy też pytasz, czy nazwa będzie dozwolona przez system operacyjny?
Jesse McCulloch
4
Ważny jak w (a) istniejący, (b) legalny lub (c) legalny i nieistniejący?
Anthony Pegram
Sry, powinienem to wyjaśnić. Powinien być (c) leagl i nieistniejący
RoflcoptrException
4
@roflcopter: Musisz po prostu obsłużyć błędy podczas tworzenia pliku. Każda operacja na systemie plików, która wymaga sprawdzenia istnienia, jest potencjalnie nieaktualna w momencie powrotu, ponieważ system plików jest globalnym zasobem współdzielonym.
Ben Voigt,
1
@Roflcoptr: plik o dokładnie tej samej nazwie, tworzony między momentem sprawdzenia ważności i / lub istnienia, a momentem, w którym faktycznie próbujesz go utworzyć, nie powinien być uważany za normalny przepływ programu. Państwo powinno zweryfikować, że plik nie istnieje, ale jeśli faktycznie utworzyć plik, że wiedza jest już stary i powinien być uważany tylko zgaduje. Prawdopodobnie nadal będzie to prawda, ale nie jest to gwarantowane .
Fredrik Mörk

Odpowiedzi:

125

Sprawdź, czy filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0i!File.Exists(Path.Combine(someFolder, filename))

SLaks
źródło
3
<quote> Nie ma gwarancji, że tablica zwrócona przez tę metodę będzie zawierać pełny zestaw znaków, które są nieprawidłowe w nazwach plików i katalogów. </quote> Ponadto ta właściwość jest przestarzała.
Ben Voigt,
4
kontrprzykład: "http://www.microsoft.com/"zdaje test, ale nie jest prawidłową nazwą pliku, tak samo jak"::::"
Ben Voigt
3
Więcej kontrprzykładów: „” jest nieprawidłowy i nowy ciąg („x”, 1024) również nie jest prawidłowy.
Rasmus Faber,
2
@shellster Możesz zmienić nazwę pliku na „.txt” w Eksploratorze Windows, mówiąc eksploratorowi, aby zmienił nazwę pliku na „.txt.”. Tylko wskazówka (lub „.txt ........” też zadziała).
Robert McKee,
2
to powinno być < 0zamiast >= 0jak IndexOfAny()zwróci -1, jeśli nic nie zostanie znalezione
Michael Tranchida
37

Sprawdź przeciwko GetInvalidFileNameChars():

var isValid = !string.IsNullOrEmpty(fileName) &&
              fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
              !File.Exists(Path.Combine(sourceFolder, fileName));
Phil Hunt
źródło
2
kontrprzykład: "http://www.microsoft.com/"zdaje test, ale nie jest prawidłową nazwą pliku, tak samo jak"::::"
Ben Voigt
1
@Ben Voigt: Masz rację, która ::::została błędnie uznana za ważną. Poprawiłem odpowiedź, aby wskazać < 0zamiast == 0.
Phil Hunt
1
Och, właśnie zauważyłem, że używasz GetInvalidFileNameChars, a nie GetInvalidPathCharsSLaksów. Tak długo, jak jest to test tylko dla nazwy pliku, a nie nazwy pliku ze ścieżką, wszystko będzie w porządku.
Ben Voigt,
@Ben Voigt: Ponieważ OP zapytał o walidację nazw plików i ścieżek tylko niejawnie w celu sprawdzenia nieistnienia pliku, użyłem GetInvalidFileNameChars:-)
Phil Hunt
11

Jeśli plik ma zostać utworzony, należy użyć okna dialogowego pliku, aby określić ścieżkę do katalogu. Istnieje krótka lista niedozwolonych znaków w nazwach plików.

Jedynym naprawdę niezawodnym sposobem sprawdzenia, czy nazwa pliku jest akceptowalna, jest wypróbowanie jej. Pozwolenia to grzęzawisko.

ddyer
źródło
Okno dialogowe pliku to czerwony śledź, ale +1 za „jedyną naprawdę niezawodną metodą ... jest wypróbowanie”.
Ben Voigt,
1
Zgoda. Nawet jeśli nazwa pliku nie istnieje i nie zawiera niedozwolonych znaków, istnieje wiele powodów, dla których plik nie zostanie utworzony, z których najbardziej oczywistym jest brak uprawnień do tworzenia katalogu.
Bob Kaufman,
Są przypadki, w których musisz zapisać na nieznanej ścieżce, ale nie chcesz, aby użytkownik wybierał dokładną ścieżkę. W takich przypadkach okno dialogowe pliku nie jest możliwe.
Josh Noe,
2

Używam tego:

public static bool IsValidFileName(string name) {
    if(string.IsNullOrWhiteSpace(name)) return false;
    if(name.Length > 1 && name[1] == ':') {
        if(name.Length < 4 || name.ToLower()[0] < 'a' || name.ToLower()[0] > 'z' || name[2] != '\\') return false;
        name = name.Substring(3);
    }
    if(name.StartsWith("\\\\")) name = name.Substring(1);
    if(name.EndsWith("\\") || !name.Trim().Equals(name) || name.Contains("\\\\") ||
        name.IndexOfAny(Path.GetInvalidFileNameChars().Where(x=>x!='\\').ToArray()) >= 0) return false;
    return true;
}

Powinien zająć się wszystkim oprócz zastrzeżonych nazw, uprawnień i ograniczeń długości. Akceptuje zarówno względne, jak i bezwzględne nazwy plików.

Duke Nukem
źródło
0

To tylko pomysł. Listę wyjątków należy wypełnić:

public static bool IsValidFilename(string filename)
{
    try
    {
        File.OpenRead(filename).Close();
    }
    catch (ArgumentException) { return false; }
    catch (Exception) { }
    return true;
}
Bitterblue
źródło
A jeśli plik jeszcze nie istnieje?
Mike Cheel
@MikeCheel Kod zwraca fałsz tylko wtedy, gdy zostanie zgłoszony wyjątek argumentu. Ten wyjątek jest zgłaszany tylko wtedy, gdy nazwa pliku jest nieprawidłowa.
Burak