例如,我该如何制作
"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt"
相对于此文件夹
"C:\RootFolder\SubFolder\"
如果预期结果是
"MoreSubFolder\LastFolder\SomeFile.txt"
答案 0 :(得分:35)
是的,您可以这样做,很容易,将您的路径视为URI :
Uri fullPath = new Uri(@"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt", UriKind.Absolute);
Uri relRoot = new Uri(@"C:\RootFolder\SubFolder\", UriKind.Absolute);
string relPath = relRoot.MakeRelativeUri(fullPath).ToString();
// relPath == @"MoreSubFolder\LastFolder\SomeFile.txt"
答案 1 :(得分:15)
在您的示例中,它只是absPath.Substring(relativeTo.Length)
。
更详细的示例需要从relativeTo
返回几个级别,如下所示:
"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt"
"C:\RootFolder\SubFolder\Sibling\Child\"
制作相对路径的算法如下所示:
"C:\RootFolder\SubFolder\"
)relativeTo
中的文件夹数量(在这种情况下,它是2:"Sibling\Child\"
)..\
最终结果如下:
"..\..\MoreSubFolder\LastFolder\SomeFile.txt"
答案 2 :(得分:1)
这是我的5美分,没有为此目的使用任何特殊的Url类。
在以下git存储库中搜索makeRelative
:https://github.com/tapika/syncProj/blob/8ea41ebc11f538a22ed7cfaf59a8b7e0b4c3da37/syncProj.cs#L1685
(固定版一次冻结,分别搜索最新版本)
如果有错误,我会修复错误。
以下是上述链接中相同代码的副本:
/// <summary>
/// Rebases file with path fromPath to folder with baseDir.
/// </summary>
/// <param name="_fromPath">Full file path (absolute)</param>
/// <param name="_baseDir">Full base directory path (absolute)</param>
/// <returns>Relative path to file in respect of baseDir</returns>
static public String makeRelative(String _fromPath, String _baseDir)
{
String pathSep = "\\";
String fromPath = Path.GetFullPath(_fromPath);
String baseDir = Path.GetFullPath(_baseDir); // If folder contains upper folder references, they gets lost here. "c:\test\..\test2" => "c:\test2"
String[] p1 = Regex.Split(fromPath, "[\\\\/]").Where(x => x.Length != 0).ToArray();
String[] p2 = Regex.Split(baseDir, "[\\\\/]").Where(x => x.Length != 0).ToArray();
int i = 0;
for (; i < p1.Length && i < p2.Length; i++)
if (String.Compare(p1[i], p2[i], true) != 0) // Case insensitive match
break;
if (i == 0) // Cannot make relative path, for example if resides on different drive
return fromPath;
String r = String.Join(pathSep, Enumerable.Repeat("..", p2.Length - i).Concat(p1.Skip(i).Take(p1.Length - i)));
return r;
}
答案 3 :(得分:-2)
为什么所有这些复杂的解决方案?
并涉及到Uri?真的吗?您不必等待第一个例外
简洁明了。
不需要任何额外的框架类。
public static string BuildRelativePath(string absolutePath, string basePath)
{
return absolutePath.Substring(basePath.Length);
}
以防你无法总是添加或总是忽略关闭System.IO.Path.DirectorySeparatorChar到你的字符串,或者你不能混淆参数:
public static string FaultTolerantRelativePath(string absolutePath, string basePath)
{
if(absolutePath == null || basePath == null)
return null;
absolutePath = absolutePath.Replace(System.IO.Path.DirectorySeparatorChar, '/');
basePath = basePath.Replace(System.IO.Path.DirectorySeparatorChar, '/');
if (!basePath.EndsWith("/"))
basePath += "/";
if (!absolutePath.EndsWith("/"))
absolutePath += "/";
if (absolutePath.Length < basePath.Length)
throw new ArgumentException("absolutePath.Length < basePath.Length ? This can't be. You mixed up absolute and base path.");
string resultingPath = absolutePath.Substring(basePath.Length);
resultingPath = resultingPath.Replace('/', System.IO.Path.DirectorySeparatorChar);
return resultingPath;
}