由于.NET不包含用于创建相对路径的API,因此我使用了Uri的MakeRelativeUri
方法。这样可行,但我遇到过几种情况,因为Uri没有被转义。所以我也补了一下:
public static string MakeRelativePath(string basePath, string tgtPath) {
return
Uri.UnescapeDataString(
new Uri(basePath, UriKind.Absolute)
.MakeRelativeUri(new Uri(tgtPath, UriKind.Absolute))
.ToString()
).Replace('/', Path.DirectorySeparatorChar);
}
这个版本的似乎可以工作,但是让我感到有些疑问:这个无偿的unescaping可能会破坏任何有效的本地文件系统路径吗?
相关: How to get relative path from absolute path 这个问题的答案并没有解决不寻常的角色和逃避的问题,因此不回答这个问题。
答案 0 :(得分:4)
您可以使用System.Uri
和PathDifference
方法使用的基础算法,而不是转义,取消转换和替换。在这里,它通过Reflector恢复并进行了修改,以获得更好的可读性。它也被修改为对DOS样式路径使用反斜杠而不是URI的正斜杠,并且比较总是不区分大小写。
static string PathDifference(string path1, string path2)
{
int c = 0; //index up to which the paths are the same
int d = -1; //index of trailing slash for the portion where the paths are the same
while (c < path1.Length && c < path2.Length)
{
if (char.ToLowerInvariant(path1[c]) != char.ToLowerInvariant(path2[c]))
{
break;
}
if (path1[c] == '\\')
{
d = c;
}
c++;
}
if (c == 0)
{
return path2;
}
if (c == path1.Length && c == path2.Length)
{
return string.Empty;
}
System.Text.StringBuilder builder = new System.Text.StringBuilder();
while (c < path1.Length)
{
if (path1[c] == '\\')
{
builder.Append(@"..\");
}
c++;
}
if (builder.Length == 0 && path2.Length - 1 == d)
{
return @".\";
}
return builder.ToString() + path2.Substring(d + 1);
}
输入的期望似乎是,如果任一路径表示目录,则它必须具有尾部反斜杠。显然,路径也必须是非空的。
以下是一些示例输入和输出......看看它是否符合您的需求。
Path1 Path2 Output
C:\test\path1\path2\ C:\test\ ..\..\
C:\test\path1\file C:\test\ ..\
C:\test\path1\path2\ C:\ ..\..\..\
C:\test\path1\path2\ D:\ D:\
C:\test\path1\path2\ C:\test\path1\pathA ..\pathA
C:\test\ C:\test\
C:\test\ C:\test\file file
C:\test\file C:\test\ .\
C:\test\path #1!\path2\ C:\test\ ..\..\