2011-04-06 15 views
68

¿Existe algún método para verificar si una ruta dada es de ruta completa? En este momento estoy haciendo esto:Verifique si se proporcionó la ruta completa

if (template.Contains(":\\")) //full path already given 
{ 
} 
else //calculate the path from local assembly 
{ 
} 

Pero debe haber una manera más elegante para verificar esto?

Respuesta

102

Intente con System.IO.Path.IsPathRooted? También devuelve true para rutas absolutas.

System.IO.Path.IsPathRooted(@"c:\foo"); // true 
System.IO.Path.IsPathRooted(@"\foo"); // true 
System.IO.Path.IsPathRooted("foo"); // false 

System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true 
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo" 
+6

¿Cómo es que sea segundo ejemplo de ruta absoluta? – om471987

+1

La segunda ruta no es absoluta, sin embargo está enraizada. La barra diagonal indica la raíz del sistema. – detaylor

+1

@SmirkinGherkin, entonces, ¿cuál es la diferencia entre una ruta enraizada y absoluta? –

0

No estoy realmente seguro de lo que entendemos por ruta completa (aunque asumiendo el ejemplo que quiere decir que no es pariente de la raíz en adelante), así, se puede utilizar la clase Path para ayudarle en trabajando con rutas físicas del sistema de archivos, que deberían cubrirlo para la mayoría de las eventualidades.

14

Trate

System.IO.Path.IsPathRooted(template) 

Obras para rutas UNC, así como los locales.

E.g.

Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory") // returns true 
Path.IsPathRooted(@"C:\\MyDirectory") // returns true 
+5

Thnx, pero Smirkin fue el primero y solo puede aceptar una respuesta (: – hs2d

10

Pregunta anterior, pero una respuesta más aplicable. Si es necesario asegurarse de que el volumen se incluye en una ruta local, puede utilizar System.IO.Path.GetFullPath() así:

if (template == System.IO.Path.GetFullPath(template)) 
{ 
    ; //template is full path including volume or full UNC path 
} 
else 
{ 
    if (useCurrentPathAndVolume) 
     template = System.IO.Path.GetFullPath(template); 
    else 
     template = Assembly.GetExecutingAssembly().Location 
} 
+3

Esto era lo que necesitaba, y parece más cercano a la pregunta original ya que IsPathRooted 'devuelve verdadero para rutas relativas (rutas no necesariamente absolutas) – bitcoder

+0

'GetFullPath' accede al sistema de archivos y puede arrojar una serie de excepciones posibles. Consulte mi respuesta (http://stackoverflow.com/a/35046453/704808) para obtener una alternativa que aún garantiza una ruta completa. – weir

11
Path.IsPathRooted(path) 
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) 

La condición anterior:

  • hace no requiere permisos del sistema de archivos
  • vuelve false en la mayoría de los casos en que el formato de path no es válido (en lugar de tirar una excepción)
  • devuelve true sólo si path incluye el volumen

En escenarios como el de la OP plantea, puede por lo tanto ser más adecuado que las condiciones en las respuestas anteriores. A diferencia de la condición anterior:

  • path == System.IO.Path.GetFullPath(path) tiros excepciones en lugar de volver false en estos escenarios:
    • El llamador no tiene los permisos requeridos
    • El sistema no ha podido recuperar la ruta absoluta
    • ruta contiene dos puntos (":") que no forman parte de un identificador de volumen
    • La ruta especificada, nombre de archivo, o ambos exceden la longitud máxima definida por el sistema
  • System.IO.Path.IsPathRooted(path) rendimientos true si path comienza con un solo separador de directorio.

Por último, aquí es un método que envuelve la condición anterior, y también excluye las restantes excepciones posibles:

public static bool IsFullPath(string path) { 
    return !String.IsNullOrWhiteSpace(path) 
     && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1 
     && Path.IsPathRooted(path) 
     && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal); 
} 

EDIT: EM0 hizo un buen comentario y alternative answer abordar el caso curioso de caminos como C: y C:dir. Para ayudar a decidir cómo es posible que desee manejar este tipo de caminos, es posible que desee tomar inmersión profunda a MSDN ->aplicaciones de escritorio de Windows -> Desarrollar -> tecnologías de escritorio ->de acceso a datos y almacenamiento ->sistemas de archivos locales -> Administración de archivos -> Acerca de Administración de archivos ->crear, eliminar, y el mantenimiento de archivos ->Denominación de archivos, rutas y espacios de nombres - >Fully Qualified vs. Relative Paths

Para las funciones de API de Windows que manipulan archivos, los nombres de archivos a menudo pueden ser relativos al directorio actual, mientras que algunas API requieren una ruta calificada totalmente . Un nombre de archivo es relativa al directorio actual si no comienza con uno de los siguientes:

  • nombre de un UNC de cualquier formato, que siempre comienza con dos caracteres de barra invertida ("\"). Para obtener más información, consulte la siguiente sección.
  • Un designador de disco con una barra diagonal inversa, por ejemplo "C: \" o "d: \".
  • Una sola barra diagonal inversa, por ejemplo, "\ directorio" o "\ archivo.txt". Esto también se conoce como una ruta absoluta.

Si un nombre de archivo comienza con solamente un designador de disco pero no la barra invertida tras los dos puntos, se interpreta como una ruta relativa al directorio actual en la unidad con la letra especificada. Tenga en cuenta que el directorio actual puede ser o no el directorio raíz según en el que se configuró durante la operación más reciente de "cambio de directorio" en ese disco. Los ejemplos de este formato son los siguientes:

  • "C: tmp.txt" se refiere a un archivo llamado "tmp.txt" en el directorio actual en la unidad C.
  • "C: tempdir \ tmp.txt "se refiere a un archivo en un subdirectorio en el directorio actual en la unidad C.

[...]

+2

Me gusta que esto no arroje caminos inválidos, pero devuelve verdadero para rutas como "C:" y "C: dir", que son resueltas por GetFullPath usando el directorio actual (para que no sean absoluto). Publicó una respuesta que devuelve falso para estos. – EM0

+0

@ EM0 - ¡Gracias! Acaba de enseñarme algo :) – weir

1

Basándose en respuesta vertedero 's: este no tira de caminos válidos, pero también devuelve false para rutas como "C:", "C: dirname" y "\ path".

public static bool IsFullPath(string path) 
    { 
     if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path)) 
      return false; 

     var pathRoot = Path.GetPathRoot(path); 
     if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts/to support Linux 
      return false; 

     return !(pathRoot == path && pathRoot.StartsWith("\\\\") && pathRoot.IndexOf('\\', 2) == -1); // A UNC server name without a share name (e.g "\\NAME") is invalid 
    } 

Tenga en cuenta que esto arroja resultados diferentes en Windows y Linux, p. Ej. "/ ruta" es absoluta en Linux, pero no en Windows.

Unidad de prueba:

[Test] 
    public void IsFullPath() 
    { 
     bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework 
     // bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core 

     // These are full paths on Windows, but not on Linux 
     TryIsFullPath(@"C:\dir\file.ext", isWindows); 
     TryIsFullPath(@"C:\dir\", isWindows); 
     TryIsFullPath(@"C:\dir", isWindows); 
     TryIsFullPath(@"C:\", isWindows); 
     TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows); 
     TryIsFullPath(@"\\unc\share", isWindows); 

     // These are full paths on Linux, but not on Windows 
     TryIsFullPath(@"/some/file", !isWindows); 
     TryIsFullPath(@"/dir", !isWindows); 
     TryIsFullPath(@"/", !isWindows); 

     // Not full paths on either Windows or Linux 
     TryIsFullPath(@"file.ext", false); 
     TryIsFullPath(@"dir\file.ext", false); 
     TryIsFullPath(@"\dir\file.ext", false); 
     TryIsFullPath(@"C:", false); 
     TryIsFullPath(@"C:dir\file.ext", false); 
     TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path 

     // Invalid on both Windows and Linux 
     TryIsFullPath(null, false, false); 
     TryIsFullPath("", false, false); 
     TryIsFullPath(" ", false, false); 
     TryIsFullPath(@"C:\inval|d", false, false); 
     TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false); 
    } 

    private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true) 
    { 
     Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')"); 

     if (expectedIsFull) 
     { 
      Assert.AreEqual(path, Path.GetFullPath(path)); 
     } 
     else if (expectedIsValid) 
     { 
      Assert.AreNotEqual(path, Path.GetFullPath(path)); 
     } 
     else 
     { 
      Assert.That(() => Path.GetFullPath(path), Throws.Exception); 
     } 
    } 
+0

Cosas buenas. Me di cuenta de que https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#fully_qualified_vs._relative_paths indica que en Windows una ruta es * no * relativa si comienza con * 'Una barra invertida única, por ejemplo, "\ directorio" o "\ archivo.txt". Esto también se conoce como una ruta absoluta. '* – weir

+1

¡Buen punto! Parece que mi terminología estaba apagada. Cuando dije "camino absoluto", realmente estaba pensando en lo que MS llama un "camino completo". Cambié el nombre y agregué un caso de prueba para esto. – EM0

Cuestiones relacionadas