Compruebe si una ruta es válida

110

Solo me pregunto: estoy buscando una forma de validar si una ruta determinada es válida. (Nota: ¡No quiero verificar si existe un archivo! Solo quiero probar la validez de la ruta, por lo tanto, si es posible que exista un archivo en la ubicación) .

El problema es que no puedo encontrar nada en la API .Net. Debido a los muchos formatos y ubicaciones que admite Windows, prefiero usar algo nativo de MS.

Dado que la función debería poder comprobarse con:

  • Rutas relativas (./)
  • Rutas absolutas (c: \ tmp)
  • UNC-Pathes (\ some-pc \ c $)
  • Limitaciones de NTFS como la ruta completa 1024 caracteres: si no me equivoco, exceder la ruta hará que un archivo sea inaccesible para muchas funciones internas de Windows. Cambiarle el nombre con Explorer todavía funciona
  • Rutas de GUID de volumen: "\? \ Volume {GUID} \ somefile.foo

¿Alguien tiene una función como esta?

Tobias Boschek
fuente

Respuestas:

58

Prueba Uri.IsWellFormedUriString():

  • La cadena no se escapó correctamente.

    http://www.example.com/path???/file name
  • La cadena es un Uri absoluto que representa un Uri de archivo implícito.

    c:\\directory\filename
  • La cadena es un URI absoluto al que le falta una barra antes de la ruta.

    file://c:/directory/filename
  • La cadena contiene barras diagonales inversas sin escape incluso si se tratan como barras diagonales.

    http:\\host/path/file
  • La cadena representa un Uri absoluto jerárquico y no contiene ": //".

    www.example.com/path/file
  • El analizador del Uri.Scheme indica que la cadena original no estaba bien formada.

    The example depends on the scheme of the URI.
abatishchev
fuente
9
Esto devuelve falso para @"foo\bar\baz", que es una ruta relativa perfectamente válida ...
Thomas Levesque
5
Thomas: ¿Qué UriKind especificaste? Puede utilizar Absolute, Relative o AbsoluteOrRelative.
Dan Gøran Lunde
1
Incluso con UriKind como Relative o AbsoluteOrRelative, no funcionó para rutas relativas como Thomas mencionó. Terminé usando la respuesta de Patko en su lugar y funciona para mis propósitos.
JohnnyM
1
Descubrí que una ruta como \\ computerName \ Dir Name With Spaces \ fileName arroja una excepción al usar IsWellFormedUriString (contrariamente a mi expectativa inicial), porque los espacios no están codificados correctamente. Descubrí que podía usar el constructor Uri (cadena) como mi validación, por lo que no tenía que codificar correctamente la cadena antes de validar.
excelencia 5
3
Devuelve falso en una ruta de archivo perfectamente correcta.
Evgeni Petrov
7
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;

    DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
    if (!dir.Exists)
        dir.Create();
    return true;
}
Alex Jolig
fuente
7

No he tenido ningún problema con el siguiente código. (Las rutas relativas deben comenzar con '/' o '\').

private bool IsValidPath(string path, bool allowRelativePaths = false)
{
    bool isValid = true;

    try
    {
        string fullPath = Path.GetFullPath(path);

        if (allowRelativePaths)
        {
            isValid = Path.IsPathRooted(path);
        }
        else
        {
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
        }
    }
    catch(Exception ex)
    {
        isValid = false;
    }

    return isValid;
}

Por ejemplo, estos devolverían falso:

IsValidPath("C:/abc*d");
IsValidPath("C:/abc?d");
IsValidPath("C:/abc\"d");
IsValidPath("C:/abc<d");
IsValidPath("C:/abc>d");
IsValidPath("C:/abc|d");
IsValidPath("C:/abc:d");
IsValidPath("");
IsValidPath("./abc");
IsValidPath("./abc", true);
IsValidPath("/abc");
IsValidPath("abc");
IsValidPath("abc", true);

Y estos volverían verdaderos:

IsValidPath(@"C:\\abc");
IsValidPath(@"F:\FILES\");
IsValidPath(@"C:\\abc.docx\\defg.docx");
IsValidPath(@"C:/abc/defg");
IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
IsValidPath(@"C:/abc/def~`!@#$%^&()_-+={[}];',.g");
IsValidPath(@"C:\\\\\abc////////defg");
IsValidPath(@"/abc", true);
IsValidPath(@"\abc", true);
Buscador de Dao
fuente
3

Puedes probar este código:

try
{
  Path.GetDirectoryName(myPath);
}
catch
{
  // Path is not valid
}

No estoy seguro de que cubra todos los casos ...

Nimrod
fuente
2

Lo más cerca que he estado es intentar crearlo y ver si tiene éxito.

Martijn
fuente
2

Hay muchas buenas soluciones aquí, pero como ninguna de ellas verifica si la ruta está enraizada en una unidad existente, aquí hay otra:

private bool IsValidPath(string path)
{
    // Check if the path is rooted in a driver
    if (path.Length < 3) return false;
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;

    // Check if such driver exists
    IEnumerable<string> allMachineDrivers = DriveInfo.GetDrives().Select(drive => drive.Name);
    if (!allMachineDrivers.Contains(path.Substring(0, 3))) return false;

    // Check if the rest of the path is valid
    string InvalidFileNameChars = new string(Path.GetInvalidPathChars());
    InvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(InvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;
    if (path[path.Length - 1] == '.') return false;

    return true;
}

Esta solución no tiene en cuenta las rutas relativas.

Gark García
fuente
1

Obtenga los caracteres no válidos de System.IO.Path.GetInvalidPathChars();y verifique si su cadena (ruta del directorio) los contiene o no.

Umesh CHILAKA
fuente
3
Esto no es del todo válido. "C: \ new.folder" es válido mientras que "C: \ newfolder". no es. '.' es un carácter válido para rutas / nombres de archivo, pero no al final del uri.
claudekennilol
0

Directorio ¿Existe?

Markpsmith
fuente
4
"[...] no quiero comprobar si existe un archivo!"
Stefan
3
Esa prueba para el directorio existente, no para que sea una ruta válida (donde podría existir, o ser creado, con los privilegios adecuados)
Martijn
3
@Jason: no verifica el archivo, solo la carpeta que lo contiene.
markpsmith
8
pero aún no puede existir una ruta de directorio válida.
Stefan
-2
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");

    if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
    {
        return false;
    }

    if (!driveCheck.IsMatch(path.Substring(0, 3)))
    {
        return false;
    }

    var x1 = (path.Substring(3, path.Length - 3));
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":?*";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");

    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
    {
        return false;
    }

    var driveLetterWithColonAndSlash = Path.GetPathRoot(path);

    if (!DriveInfo.GetDrives().Any(x => x.Name == driveLetterWithColonAndSlash))
    {
        return false;
    }

    return true;
}
Ghislain Zabatio
fuente
1
¿Cuál es el propósito de x1?
JayJay
-3

Simplemente use

if (System.IO.Directory.Exists(path))
{
    ...
}
Mahdi Astanei
fuente
-4

Puede intentar usar Path.IsPathRooted () en combinación con Path.GetInvalidFileNameChars () para asegurarse de que la ruta esté bien a mitad de camino.

Alen Milakovic
fuente