Récemment, j'ai déplacé un tas de MP3 de divers endroits dans un référentiel. J'avais construit les nouveaux noms de fichiers en utilisant les balises ID3 (merci, TagLib-Sharp!), Et j'ai remarqué que j'obtenais un System.NotSupportedException
:
"Le format du chemin donné n'est pas pris en charge."
Cela a été généré par File.Copy()
ou par Directory.CreateDirectory()
.
Il n'a pas fallu longtemps pour réaliser que mes noms de fichiers devaient être nettoyés. Alors j'ai fait la chose évidente:
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;
}
À ma grande surprise, j'ai continué à recevoir des exceptions. Il s'est avéré que «:» n'est pas dans l'ensemble de Path.GetInvalidPathChars()
, car il est valide dans une racine de chemin. Je suppose que cela a du sens - mais cela doit être un problème assez courant. Quelqu'un a-t-il un code court qui nettoie un chemin? Le plus approfondi que j'ai proposé, mais j'ai l'impression que c'est probablement exagéré.
// 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());
}
Toute amélioration pour rendre cette fonction plus rapide et moins baroque serait très appréciée.
la source
Réponses:
Pour nettoyer un nom de fichier, vous pouvez le faire
la source
GetInvalidFileNameChars
ne les incluent donc pas. Il ne lève pas d'exception dans les fenêtres, il les supprime simplement, mais cela pourrait provoquer un comportement inattendu si vous vous attendez à ce que la période soit là. J'ai modifié l'expression rationnelle pour gérer ce cas afin.
d'être considéré comme l'un des caractères invalides s'il se trouve à la fin de la chaîne.Une solution plus courte:
la source
Sur la base de l'excellente réponse d'André mais en tenant compte du commentaire de Spud sur les mots réservés, j'ai fait cette version:
Et ce sont mes tests unitaires
la source
COM1
), qui sont également interdites. La solution suggérée serait de changer le reservedWordPattern en"^{0}(\\.|$)"
et la chaîne de remplacement en"_reservedWord_$1"
la source
String.Concat(dirty...)
au lieu deJoin(String.Empty...
J'utilise la
System.IO.Path.GetInvalidFileNameChars()
méthode pour vérifier les caractères invalides et je n'ai aucun problème.J'utilise le code suivant:
la source
Je voulais conserver les caractères d'une certaine manière, pas simplement remplacer le caractère par un trait de soulignement.
Une façon dont j'ai pensé était de remplacer les caractères par des caractères similaires qui sont (dans ma situation) peu susceptibles d'être utilisés comme caractères normaux. J'ai donc pris la liste des caractères invalides et j'ai trouvé des sosies.
Ce qui suit sont des fonctions pour encoder et décoder avec les look-a-likes.
Ce code n'inclut pas une liste complète pour tous les caractères System.IO.Path.GetInvalidFileNameChars (). C'est donc à vous d'étendre ou d'utiliser le remplacement de soulignement pour tous les caractères restants.
Vous pouvez sélectionner vos propres looks-a-likes. J'ai utilisé l'application Character Map dans Windows pour sélectionner la mienne
%windir%\system32\charmap.exe
Au fur et à mesure que je fais des ajustements grâce à la découverte, je mettrai à jour ce code.
la source
!"#$%&'()*+,-./:;<=>?@{|}~
ou d'autres formes de ceux-ci comme/
SOLIDUS et `⁄` FRACTION SLASH qui peuvent être utilisés directement dans les noms de fichiers sans problèmeJe pense que le problème est que vous appelez d'abord
Path.GetDirectoryName
la mauvaise chaîne. Si cela contient des caractères sans nom de fichier, .Net ne peut pas dire quelles parties de la chaîne sont des répertoires et des renvois. Vous devez faire des comparaisons de chaînes.En supposant que seul le nom de fichier est incorrect, pas le chemin complet, essayez ceci:
la source
J'ai eu du succès avec cela dans le passé.
Sympa, court et statique :-)
la source
il y a beaucoup de solutions de travail ici. juste pour des raisons d'exhaustivité, voici une approche qui n'utilise pas regex, mais utilise LINQ:
C'est aussi une solution très courte;)
la source
Voici une méthode d'extension de chargement différé efficace basée sur le code d'André:
la source
Votre code serait plus propre si vous ajoutiez le répertoire et le nom de fichier ensemble et les nettoyiez plutôt que de les nettoyer indépendamment. Pour nettoyer le:, prenez simplement le 2ème caractère de la chaîne. S'il est égal à "replacechar", remplacez-le par deux points. Puisque cette application est pour votre propre usage, une telle solution devrait être parfaitement suffisante.
la source
la source