Niedawno przenosiłem kilka plików MP3 z różnych lokalizacji do repozytorium. Konstruowałem nowe nazwy plików za pomocą tagów ID3 (dzięki, TagLib-Sharp!) I zauważyłem, że otrzymuję System.NotSupportedException
:
„Format podanej ścieżki nie jest obsługiwany”.
Zostało to wygenerowane przez albo File.Copy()
lub Directory.CreateDirectory()
.
Nie trwało długo, zanim zdałem sobie sprawę, że moje nazwy plików wymagają oczyszczenia. Zrobiłem więc oczywistą rzecz:
public static string SanitizePath_(string path, char replaceChar)
{
string dir = Path.GetDirectoryName(path);
foreach (char c in Path.GetInvalidPathChars())
dir = dir.Replace(c, replaceChar);
string name = Path.GetFileName(path);
foreach (char c in Path.GetInvalidFileNameChars())
name = name.Replace(c, replaceChar);
return dir + name;
}
Ku mojemu zdziwieniu nadal otrzymywałem wyjątki. Okazało się, że ':' nie znajduje się w zbiorze Path.GetInvalidPathChars()
, ponieważ jest poprawne w katalogu głównym ścieżki. Myślę, że to ma sens - ale to musi być dość powszechny problem. Czy ktoś ma jakiś krótki kod, który oczyszcza ścieżkę? Najdokładniejszy, jaki wymyśliłem, ale wydaje mi się, że to prawdopodobnie przesada.
// replaces invalid characters with replaceChar
public static string SanitizePath(string path, char replaceChar)
{
// construct a list of characters that can't show up in filenames.
// need to do this because ":" is not in InvalidPathChars
if (_BadChars == null)
{
_BadChars = new List<char>(Path.GetInvalidFileNameChars());
_BadChars.AddRange(Path.GetInvalidPathChars());
_BadChars = Utility.GetUnique<char>(_BadChars);
}
// remove root
string root = Path.GetPathRoot(path);
path = path.Remove(0, root.Length);
// split on the directory separator character. Need to do this
// because the separator is not valid in a filename.
List<string> parts = new List<string>(path.Split(new char[]{Path.DirectorySeparatorChar}));
// check each part to make sure it is valid.
for (int i = 0; i < parts.Count; i++)
{
string part = parts[i];
foreach (char c in _BadChars)
{
part = part.Replace(c, replaceChar);
}
parts[i] = part;
}
return root + Utility.Join(parts, Path.DirectorySeparatorChar.ToString());
}
Wszelkie ulepszenia, które sprawią, że ta funkcja będzie szybsza i mniej barokowa, będą bardzo mile widziane.
źródło
Odpowiedzi:
Aby wyczyścić nazwę pliku, możesz to zrobić
źródło
GetInvalidFileNameChars
ich nie uwzględnia. Nie zgłasza wyjątku w oknach, po prostu je usuwa, ale może spowodować nieoczekiwane zachowanie, jeśli spodziewasz się, że wystąpi okres. Zmodyfikowałem wyrażenie regularne, aby obsłużyć ten przypadek, aby.
było uważane za jeden z nieprawidłowych znaków, jeśli znajduje się na końcu ciągu.Krótsze rozwiązanie:
źródło
Opierając się na doskonałej odpowiedzi Andre, ale biorąc pod uwagę komentarz Spuda na temat słów zastrzeżonych, stworzyłem tę wersję:
A to są moje testy jednostkowe
źródło
COM1
), Które również są niedozwolone. Sugerowanym rozwiązaniem byłaby zmiana reservedWordPattern na"^{0}(\\.|$)"
i zastępującego ciągu na"_reservedWord_$1"
źródło
String.Concat(dirty...)
zamiastJoin(String.Empty...
Używam
System.IO.Path.GetInvalidFileNameChars()
metody do sprawdzania nieprawidłowych znaków i nie mam żadnych problemów.Używam następującego kodu:
źródło
Chciałem w jakiś sposób zachować postacie, a nie po prostu zastąpić je podkreśleniem.
Pomyślałem, że jednym ze sposobów było zastąpienie postaci podobnymi postaciami, które (w mojej sytuacji) raczej nie będą używane jako zwykłe postacie. Więc wziąłem listę nieprawidłowych znaków i znalazłem coś podobnego.
Poniżej znajdują się funkcje do kodowania i dekodowania za pomocą typu look-a-like.
Ten kod nie zawiera pełnej listy wszystkich znaków System.IO.Path.GetInvalidFileNameChars (). Więc to do Ciebie należy rozszerzenie lub wykorzystanie podkreślenia dla pozostałych znaków.
Możesz wybrać swój własny look-a-like. Użyłem aplikacji Mapa znaków w systemie Windows, aby wybrać moją
%windir%\system32\charmap.exe
W miarę wprowadzania zmian poprzez wykrywanie zaktualizuję ten kod.
źródło
!"#$%&'()*+,-./:;<=>?@{|}~
lub inne ich formy, takie jak/
SOLIDUS i `` ⁄ '' FRACTION SLASH, których można bez problemu używać bezpośrednio w nazwach plikówMyślę, że problem polega na tym, że najpierw wywołujesz
Path.GetDirectoryName
zły ciąg. Jeśli zawiera on znaki niebędące nazwami plików, .Net nie może powiedzieć, które części ciągu są katalogami i rzutami. Musisz robić porównania ciągów.Zakładając, że tylko nazwa pliku jest zła, a nie cała ścieżka, spróbuj tego:
źródło
W przeszłości odniosłem sukces.
Ładnie, krótko i statycznie :-)
źródło
jest tu wiele działających rozwiązań. tylko ze względu na kompletność, oto podejście, które nie używa wyrażenia regularnego, ale używa LINQ:
To też bardzo krótkie rozwiązanie;)
źródło
Oto wydajna metoda rozszerzenia ładowania z opóźnieniem, oparta na kodzie Andre:
źródło
Twój kod byłby czystszy, gdybyś dołączył katalog i nazwę pliku razem i wyczyścił to, zamiast czyścić je niezależnie. Jeśli chodzi o odkażanie:, po prostu weź drugi znak w ciągu. Jeśli jest równe „replaceechar”, zamień go na dwukropek. Ponieważ ta aplikacja jest na własny użytek, takie rozwiązanie powinno w zupełności wystarczyć.
źródło
źródło