相对路径在文件路径描述中非常重要,会比绝对路径更灵活、更人性化。经常用到的是相对路径转绝对路径的算法,比较简单Path.GetFullPath一句就可以搞定。网上搜了下由绝对路径转相对路径的算法,貌似结果不是太多,我就凑活了个轮子。
算法描述:已经绝对路径A和B求B相对于A的绝对路径。1.得到AB路径相同的前缀点C,2.从B回退到C点每级用../代替,3.从C点进入到A即可得到B相对A的相对路径。
实现如下:
/// <summary>
/// 得到两条路径的相对路径
/// </summary>
/// <param name="path">源路径</param>
/// <param name="targetBase">目标路径</param>
/// <returns>源路径相对目标路径的相对路径</returns>
static string GetRelativePath(string path, string targetBase)
{
System.Text.RegularExpressions.Regex replace = new System.Text.RegularExpressions.Regex("(/|\\\\)+");
// 得到源路径和目标路径的规整形式
targetBase = replace.Replace(Path.GetFullPath(targetBase), "/");
path = replace.Replace(Path.GetFullPath(path), "/");
// 将源路径调整到目录层次
if(path.EndsWith("/") == false)
path = path.Substring(0, path.LastIndexOf('/') + 1);
// 得到源路径和目标路径相同的前缀
string[] p = path.Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries);
string[] t = targetBase.Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries);
int len = Math.Min(p.Length, t.Length);
int same = 0;
for (; same < len; same++)
{
if (p[same] != t[same])
break;
}
// 若源路径和目标路径无任何相同前缀,则返回目标路径本身(绝对路径)
if (same == 0)
return targetBase;
// 构造相对路径
StringBuilder sb = new StringBuilder("./"); // 默认填充上源路径的当前路径
// 从当前路径回退到两条路径相同的地方
for (int i = same; i < p.Length; i++)
sb.Append("../");
// 从两条路径相同的地方再进入到目标路径
for (int i = same; i < t.Length; i++)
sb.Append('/').Append(t[i]);
// 如果目标路径是个目录,则源的回退应该增加一层,并调整目标路径的结尾
if (targetBase.EndsWith("/"))
{
sb.Insert(2, "../");
sb.Append('/');
}
// 返回结果
return replace.Replace(sb.ToString(), "/");
}
评论