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.
fuente
Respuestas:
Para limpiar un nombre de archivo, puede hacer esto
fuente
GetInvalidFileNameChars
que no los incluye. No arroja una excepción en Windows, solo los elimina, pero podría causar un comportamiento inesperado si espera que el período esté allí. Modifiqué la expresión regular para manejar ese caso para.
que se considere uno de los caracteres no válidos si está al final de la cadena.Una solución más corta:
fuente
Basado en la excelente respuesta de Andre, pero teniendo en cuenta el comentario de Spud sobre palabras reservadas, hice esta versión:
Y estas son mis pruebas unitarias
fuente
COM1
), Que también están prohibidas. La solución sugerida sería cambiar el ReservadoWordPattern a"^{0}(\\.|$)"
y la cadena de reemplazo a"_reservedWord_$1"
fuente
String.Concat(dirty...)
lugar deJoin(String.Empty...
Estoy usando el
System.IO.Path.GetInvalidFileNameChars()
método para verificar caracteres no válidos y no tengo problemas.Estoy usando el siguiente código:
fuente
Quería retener a los personajes de alguna manera, no solo reemplazar el personaje con un guión bajo.
Una forma en que pensé fue reemplazar los caracteres con caracteres similares que, en mi situación, es poco probable que se usen como caracteres normales. Así que tomé la lista de caracteres no válidos y encontré look-a-likes.
Las siguientes son funciones para codificar y decodificar con look-a-likes.
Este código no incluye una lista completa de todos los caracteres System.IO.Path.GetInvalidFileNameChars (). Por lo tanto, depende de usted extender o utilizar el reemplazo de subrayado para los caracteres restantes.
Puede seleccionar sus propios look-a-likes. Usé la aplicación Mapa de caracteres en Windows para seleccionar la mía
%windir%\system32\charmap.exe
A medida que realice ajustes a través del descubrimiento, actualizaré este código.
fuente
!"#$%&'()*+,-./:;<=>?@{|}~
u otras formas de ellos como/
SOLIDUS y `⁄` FRACTION SLASH que se pueden usar directamente en nombres de archivos sin problemasCreo que el problema es que primero invocas
Path.GetDirectoryName
la cadena incorrecta. Si esto tiene caracteres que no son de nombre de archivo, .Net no puede decir qué partes de la cadena son directorios y tiros. Tienes que hacer comparaciones de cadenas.Asumiendo que solo el nombre del archivo es malo, no la ruta completa, intente esto:
fuente
He tenido éxito con esto en el pasado.
Agradable, corto y estático :-)
fuente
Hay muchas soluciones de trabajo aquí. solo por completar, aquí hay un enfoque que no usa expresiones regulares, pero usa LINQ:
Además, es una solución muy corta;)
fuente
Aquí hay un método eficiente de extensión de carga diferida basado en el código de Andre:
fuente
Su código sería más limpio si agregara el directorio y el nombre de archivo y los desinfecte en lugar de desinfectarlos de forma independiente. En cuanto a desinfectar:: solo toma el segundo carácter de la cadena. Si es igual a "replacechar", reemplácelo con dos puntos. Dado que esta aplicación es para su propio uso, dicha solución debería ser perfectamente suficiente.
fuente
fuente