C# 如何制作相对于特定文件夹的绝对路径?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9042861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 05:42:59  来源:igfitidea点击:

How to make an absolute path relative to a particular folder?

c#.netpath

提问by asmo

For example, how can I make this

例如,我怎样才能做到这一点

"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt"

relative to this folder

相对于这个文件夹

"C:\RootFolder\SubFolder\"

if the expected result is

如果预期的结果是

"MoreSubFolder\LastFolder\SomeFile.txt"

采纳答案by ordag

Yes, you can do that, it's easy, think of your paths as URIs:

是的,您可以这样做,这很容易,将您的路径视为 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"

回答by dasblinkenlight

In your example, it's simply absPath.Substring(relativeTo.Length).

在您的示例中,它只是absPath.Substring(relativeTo.Length).

More elaborate example would require going back a few levels from the relativeTo, as follows:

更详细的示例需要从 返回几个级别relativeTo,如下所示:

"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt"
"C:\RootFolder\SubFolder\Sibling\Child\"

The algorithm to make a relative path would look as follows:

生成相对路径的算法如下所示:

  • Remove the longest common prefix (in this case, it is "C:\RootFolder\SubFolder\")
  • Count the number of folders in relativeTo(in this case, it is 2: "Sibling\Child\")
  • Insert ..\for each remaining folder
  • Concatenate with the remainder of the absolute path after the suffix removal
  • 删除最长的公共前缀(在本例中为"C:\RootFolder\SubFolder\"
  • 计算文件夹的数量relativeTo(在这种情况下,它是 2: "Sibling\Child\"
  • ..\为每个剩余的文件夹插入
  • 去除后缀后与绝对路径的剩余部分连接

The end result looks like this:

最终结果如下所示:

"..\..\MoreSubFolder\LastFolder\SomeFile.txt"

回答by TarmoPikaro

Here is my 5-cents without using any special Url class for that purpose.

这是我的 5 美分,没有为此使用任何特殊的 Url 类。

Search for makeRelativein following git repository: https://github.com/tapika/syncProj/blob/8ea41ebc11f538a22ed7cfaf59a8b7e0b4c3da37/syncProj.cs#L1685

makeRelative在以下 git 存储库中搜索:https: //github.com/tapika/syncProj/blob/8ea41ebc11f538a22ed7cfaf59a8b7e0b4c3da37/syncProj.cs#L1685

(Fixed version frozen once upon a time, search latest version separately)

(固定版本曾被冻结,请单独搜索最新版本)

I'll fix bugs if there is any.

如果有bug,我会修复。

Here is copy of same code as in link above:

这是与上面链接中相同代码的副本:

/// <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;
}