Recientemente he estado moviendo un montón de archivos MP3 desde varias ubicaciones a un repositorio. Había estado construyendo los nuevos nombres de archivo usando las etiquetas ID3 (¡gracias, TagLib-Sharp!), Y noté que estaba obteniendo un System.NotSupportedException
:
"El formato de la ruta dada no es compatible".
Esto fue generado por cualquiera File.Copy()
o Directory.CreateDirectory()
.
No tardé mucho en darme cuenta de que mis nombres de archivo necesitaban ser desinfectados. Entonces hice lo obvio:
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;
}
Para mi sorpresa, seguí recibiendo excepciones. Resultó que ':' no está en el conjunto de Path.GetInvalidPathChars()
, porque es válido en una raíz de ruta. Supongo que tiene sentido, pero este tiene que ser un problema bastante común. ¿Alguien tiene algún código corto que desinfecte una ruta? Lo más completo que he encontrado con esto, pero parece que probablemente sea exagerado.
// 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());
}
Cualquier mejora para hacer esta función más rápida y menos barroca sería muy apreciada.