C# 路径。将绝对路径字符串与相对路径字符串组合

C# 路径。将绝对路径字符串与相对路径字符串组合,c#,.net,windows,path,filesystems,C#,.net,Windows,Path,Filesystems,我正在尝试使用将Windows路径与相对路径联接 但是,Path.Combine(@“C:\blah”,“@..\bling”)返回C:\blah\..\bling而不是C:\bling\ 有人知道如何在不编写我自己的相对路径解析器的情况下实现这一点吗(这应该不会太难)?工作原理: string relativePath = "..\\bling.txt"; string baseDirectory = "C:\\blah\\"; string absolutePath = Path.GetFu

我正在尝试使用将Windows路径与相对路径联接

但是,
Path.Combine(@“C:\blah”,“@..\bling”)
返回
C:\blah\..\bling
而不是
C:\bling\


有人知道如何在不编写我自己的相对路径解析器的情况下实现这一点吗(这应该不会太难)?

工作原理:

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

什么不起作用

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

(结果:absolutePath=“C:/blah/bling.txt”)

在组合路径上调用Path.GetFullPath


(我同意Path.Combine应该自己完成这项工作)

这将为您提供所需的一切(Path不必存在,这样才能工作)


对于windows通用应用程序
Path.GetFullPath()
不可用,您可以改用
System.Uri
类:

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

小心使用反斜杠,不要忘记它们(也不要使用两次:)

Path.GetFullPath()
不适用于相对路径

这里的解决方案既适用于相对路径,也适用于绝对路径。它在Linux+Windows上都能工作,并且保持
与文本开头的预期一致(在静止状态下,它们将被规范化)。解决方案仍然依赖于
Path.GetFullPath
通过一个小的变通方法进行修复

这是一个扩展方法,所以像
text.Canonicalize()

//
///修复“./…”等
/// 
公共静态字符串规范化(此字符串路径)
{
if(path.IsAbsolutePath())
返回路径。GetFullPath(路径);
var fakeRoot=Environment.CurrentDirectory;//为我们提供了跨平台的完整路径
var combined=Path.combined(fakeRoot,Path);
组合=路径。GetFullPath(组合);
组合收益。相对收益(fakeRoot);
}
私有静态布尔值IsAbsolutePath(此字符串路径)
{
如果(path==null)抛出新的ArgumentNullException(nameof(path));
返回
Path.IsPathRooted(路径)
&&!Path.GetPathRoot(Path).Equals(Path.directorySpeparatorChar.ToString(),StringComparison.Ordinal)
&&!Path.GetPathRoot(Path).Equals(Path.altDirectorySpeparatorChar.ToString(),StringComparison.Ordinal);
}
私有静态字符串RelativeTo(此字符串文件规范,字符串文件夹)
{
var pathUri=新Uri(filespec);
//文件夹必须以斜杠结尾
如果(!folder.EndsWith(Path.directorysepartorchar.ToString())folder+=Path.directorysepartorchar;
var folderUri=新Uri(文件夹);
返回Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri.ToString)()
.Replace(“/”,Path.directoryseportorchar));
}

我们在这里得到了不同的答案。。我不认为它是重复的,它是重复的,尽管我认为Path.GetFullName是一个更好的解决方案。你只是自相矛盾。但是谢谢你的回答。可能是重复的是,这就是我用post暗示的,只要确保baseDirectory有尾随\\,否则你会得到
C:\\blah..\\bling.txt
,这是行不通的。在这种情况下,您可以手动将它们添加到字符串中,或者执行
Path.GetFullPath(Path.Combine(baseDirectory,relativePath))
工作内容部分的结果不应该是
C:\bling.txt
?为什么基于URI的方法不起作用?根据,结果是有效的(并且是有效的)。注意:应生成
c:\windows\system32
Path.GetFullPath()和DirectoryInfo.FullName将在虚拟路径上工作。问题是,当文件实际存在时,执行过程需要FileIOPermission-true用于两个API。(请参阅MSDN)请注意,这仅在第一条路径为绝对路径时有效。它不适用于
Path.GetFullPath(Path.Combine(@“.\..\blah”,@“\bling”)
> Path.GetFullPath(Path.Combine(@"C:\blah\",@"..\bling"))
C:\bling
DirectoryInfo di = new DirectoryInfo(@"C:\blah\..\bling");
string cleanPath = di.FullName;
 Uri uri = new Uri(Path.Combine(@"C:\blah\",@"..\bling"));
 Console.WriteLine(uri.LocalPath);
string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
//OR:
//string relativePath = "\\..\\bling.txt";
//string baseDirectory = "C:\\blah";
//THEN
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);
/// <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));
}