La forma más fácil de verificar si una cadena arbitraria es un nombre de archivo válido

79

En mi aplicación, el usuario puede ingresar un nombre de archivo. Antes de procesar, me gustaría comprobar si la cadena de entrada es un nombre de archivo válido en Windows Vista.

¿Cuál es la forma más sencilla de hacerlo?

Por válido me refiero a legal y no existente

RoflcoptrException
fuente
Cuando dice un nombre de archivo válido, ¿se refiere al hecho de que el archivo existe o pregunta si el sistema operativo permitiría el nombre?
Jesse McCulloch
4
¿Válido como en (a) existente, (b) legal, o (c) legal y no existente?
Anthony Pegram
Sry debería haber aclarado eso. Debe ser (c) leagl y no existente
RoflcoptrException
4
@roflcopter: simplemente debe manejar los errores mientras crea el archivo. Cualquier operación del sistema de archivos que implique una verificación de existencia ya está potencialmente desactualizada cuando regresa, ya que el sistema de archivos es un recurso compartido global.
Ben Voigt
1
@Roflcoptr: un archivo con el mismo nombre exacto que se crea entre el momento en que verifica la validez y / o existencia, y el momento en que realmente intenta crearlo, no debe considerarse un flujo de programa normal. Usted debe verificar que no existe el archivo, pero cuando realmente crear el archivo, ya que el conocimiento es viejo y debe considerarse sólo una conjetura. Es probable que siga siendo cierto, pero no está garantizado .
Fredrik Mörk

Respuestas:

125

Compruebe si filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0y!File.Exists(Path.Combine(someFolder, filename))

SLaks
fuente
1
Sin embargo, compruebe la respuesta de Phil HUnt; parece que InvalidPathChars es una API obsoleta y, en su lugar, debería utilizar GetInvalidFileNameChars ().
GendoIkari
3
<quote> No se garantiza que la matriz devuelta por este método contenga el conjunto completo de caracteres que no son válidos en los nombres de archivos y directorios. </quote> Además, esa propiedad está obsoleta.
Ben Voigt
4
contraejemplo: "http://www.microsoft.com/"pasa la prueba, pero no es un nombre de archivo válido, lo mismo para"::::"
Ben Voigt
3
Más contraejemplos: "" no es válido y la nueva cadena ('x', 1024) tampoco es válida.
Rasmus Faber
2
@shellster Puede cambiar el nombre de un archivo a ".txt" en el explorador de Windows diciéndole al explorador que cambie el nombre del archivo a ".txt". Solo un consejo (o ".txt ........" también funcionará).
Robert McKee
37

Contrastar GetInvalidFileNameChars():

var isValid = !string.IsNullOrEmpty(fileName) &&
              fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
              !File.Exists(Path.Combine(sourceFolder, fileName));
Phil Hunt
fuente
2
contraejemplo: "http://www.microsoft.com/"pasa la prueba, pero no es un nombre de archivo válido, lo mismo para"::::"
Ben Voigt
1
@Ben Voigt: Tiene razón en que ::::se consideró incorrectamente válido. He corregido la respuesta para indicar en < 0lugar de == 0.
Phil Hunt
1
Oh, acabo de notar que estás usando GetInvalidFileNameChars, no GetInvalidPathCharscomo SLaks. Siempre que sea una prueba solo para el nombre de archivo y no para un nombre de archivo con ruta, estará bien.
Ben Voigt
@Ben Voigt: Dado que el OP preguntó sobre la validación de nombres de archivos y rutas solo implícitamente para validar la inexistencia de archivos, usé GetInvalidFileNameChars:-)
Phil Hunt
11

Si se va a crear el archivo, debe utilizar un cuadro de diálogo de archivo para especificar la ruta del directorio. Hay una breve lista de caracteres ilegales para los nombres de archivo.

La única forma verdaderamente confiable de saber si un nombre de archivo es aceptable es probarlo. Los permisos son un pantano.

ddyer
fuente
El cuadro de diálogo del archivo es una pista falsa, pero +1 para "la única manera verdaderamente confiable ... es probarlo".
Ben Voigt
1
Convenido. Incluso si el nombre del archivo no existe y no contiene caracteres ilegales, existen varias razones por las que el archivo no se creará, la más obvia es la falta de permiso de creación para el directorio.
Bob Kaufman
Hay casos en los que necesita guardar en una ruta desconocida, pero no desea que el usuario elija la ruta exacta. En estos casos, un diálogo de archivo no es viable.
Josh Noe
2

Yo uso esto:

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;
}

Debería ocuparse de todo menos de nombres reservados, permisos y restricciones de longitud. Esto acepta nombres de archivo relativos y absolutos.

Duke Nukem
fuente
0

Esto es solo una idea. Uno debe completar la lista de excepciones:

public static bool IsValidFilename(string filename)
{
    try
    {
        File.OpenRead(filename).Close();
    }
    catch (ArgumentException) { return false; }
    catch (Exception) { }
    return true;
}
Azul amargo
fuente
¿Qué pasa si el archivo aún no existe?
Mike Cheel
@MikeCheel El código solo devuelve falso si se lanza una excepción de argumento. Esa excepción solo se lanza si el nombre del archivo no es válido.
Burak