Path.Combine absoluto con cadenas de ruta relativas


94

Estoy tratando de unirme a una ruta de Windows con una ruta relativa usando Path.Combine.

Sin embargo, Path.Combine(@"C:\blah",@"..\bling")devuelve en C:\blah\..\blinglugar de C:\bling\.

¿Alguien sabe cómo lograr esto sin escribir mi propio solucionador de rutas relativas (que no debería ser demasiado difícil)?



5
Estamos recibiendo diferentes respuestas aquí ... No creo que sea un duplicado
CVertex

1
es duplicado, aunque creo que Path.GetFullName es una mejor solución.
Greg Dean

Simplemente te contradeciste. Pero gracias por la respuesta alternativa.
CVertex

Respuestas:


63

Que funciona:

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

(resultado: absolutePath = "C: \ bling.txt")

Lo que no funciona

string relativePath = "..\\bling.txt";
Uri baseAbsoluteUri = new Uri("C:\\blah\\");
string absolutePath = new Uri(baseAbsoluteUri, relativePath).AbsolutePath;

(resultado: absolutePath = "C: /blah/bling.txt")


8
Sí, eso es lo que estoy insinuando con el post
Llyle

7
Solo asegúrese de que baseDirectory tenga el \\ final, de lo contrario terminará con C:\\blah..\\bling.txty eso no funcionará. En ese caso, puede agregarlos manualmente a la cadena o hacerloPath.GetFullPath(Path.Combine(baseDirectory, relativePath))
Nelson Rothermel

5
¿No debería ser el resultado de tu sección What WorksC:\bling.txt ?
cod3monk3y

¿Por qué no funciona el método basado en URI? De acuerdo con esta respuesta , el resultado es válido (y parece que también se reconoce en Windows ).
FH



4

Para las aplicaciones universales de Windows Path.GetFullPath()no está disponible, puede usar la System.Uriclase en su lugar:

 Uri uri = new Uri(Path.Combine(@"C:\blah\",@"..\bling"));
 Console.WriteLine(uri.LocalPath);

3

Esto le dará exactamente lo que necesita (la ruta NO tiene que existir para que esto funcione)

DirectoryInfo di = new DirectoryInfo(@"C:\blah\..\bling");
string cleanPath = di.FullName;

1
Tanto Path.GetFullPath () como DirectoryInfo.FullName funcionarán en una ruta ficticia. El problema es que cuando el archivo existe realmente, el proceso de ejecución necesita FileIOPermission, cierto para ambas API. (ver MSDN)
Paul Williams

1

Tenga cuidado con las barras invertidas, no las olvide (ni las use dos veces :)

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
//OR:
//string relativePath = "\\..\\bling.txt";
//string baseDirectory = "C:\\blah";
//THEN
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

0

Path.GetFullPath() no funciona con rutas relativas.

Aquí está la solución que funciona con rutas relativas + absolutas. Funciona tanto en Linux como en Windows y mantiene ..como se esperaba al principio del texto (en reposo se normalizarán). La solución aún depende Path.GetFullPathde hacer la corrección con una pequeña solución.

Es un método de extensión, utilícelo como text.Canonicalize()

/// <summary>
///     Fixes "../.." etc
/// </summary>
public static string Canonicalize(this string path)
{
    if (path.IsAbsolutePath())
        return Path.GetFullPath(path);
    var fakeRoot = Environment.CurrentDirectory; // Gives us a cross platform full path
    var combined = Path.Combine(fakeRoot, path);
    combined = Path.GetFullPath(combined);
    return combined.RelativeTo(fakeRoot);
}
private static bool IsAbsolutePath(this string path)
{
    if (path == null) throw new ArgumentNullException(nameof(path));
    return
        Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
        && !Path.GetPathRoot(path).Equals(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}
private static string RelativeTo(this string filespec, string folder)
{
    var pathUri = new Uri(filespec);
    // Folders must end in a slash
    if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString())) folder += Path.DirectorySeparatorChar;
    var folderUri = new Uri(folder);
    return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString()
        .Replace('/', Path.DirectorySeparatorChar));
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.