Path.Combine absoluto com strings de caminho relativo


94

Estou tentando juntar um caminho do Windows com um caminho relativo usando Path.Combine.

No entanto, Path.Combine(@"C:\blah",@"..\bling")retorna em C:\blah\..\blingvez de C:\bling\.

Alguém sabe como fazer isso sem escrever meu próprio resolvedor de caminho relativo (o que não deve ser muito difícil)?



5
Estamos recebendo respostas diferentes aqui .. Não acho que seja uma duplicata
CVertex

1
é duplicado, embora eu ache que Path.GetFullName é uma solução melhor.
Greg Dean,

Você apenas se contradisse. Mas obrigado pela resposta alternativa.
CVertex

Respostas:


63

O que funciona:

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

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

O que não 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
Sim, é isso que estou insinuando com o post
Llyle

7
Apenas certifique-se de que baseDirectory tenha o \\ final, caso contrário, você terminará com C:\\blah..\\bling.txte isso não funcionará. Nesse caso, você pode adicioná-los manualmente à string ou fazerPath.GetFullPath(Path.Combine(baseDirectory, relativePath))
Nelson Rothermel

5
Não deveria ser o resultado de sua seção O que funcionaC:\bling.txt ?
cod3monk3y

Por que o método baseado em URI não funciona? De acordo com esta resposta , o resultado é válido (e parece ser reconhecido no Windows também ).
FH



4

Para aplicativos universais do Windows Path.GetFullPath()não disponíveis, você pode usar a System.Uriclasse em seu lugar:

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

3

Isso lhe dará exatamente o que você precisa (o caminho NÃO precisa existir para que funcione)

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

1
Tanto Path.GetFullPath () quanto DirectoryInfo.FullName funcionarão em um caminho fictício. O problema é que, quando o arquivo realmente existe, o processo de execução precisa de FileIOPermission - verdadeiro para ambas as APIs. (veja MSDN)
Paul Williams de

1

Tenha cuidado com as barras invertidas, não se esqueça delas (nem use duas vezes :)

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() não funciona com caminhos relativos.

Esta é a solução que funciona com caminhos relativos + absolutos. Funciona tanto em Linux + Windows e mantém ..como esperado no início do texto (em repouso eles serão normalizados). A solução ainda depende Path.GetFullPathde fazer a correção com uma pequena solução alternativa.

É um método de extensão, então use-o 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));
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.