【问题标题】:How to make an absolute path relative to a particular folder?如何创建相对于特定文件夹的绝对路径?
【发布时间】:2012-02-21 00:09:59
【问题描述】:

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

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

相对于这个文件夹

"C:\RootFolder\SubFolder\"

如果预期结果是

"MoreSubFolder\LastFolder\SomeFile.txt"

【问题讨论】:

  • 预期的结果不是“MoreSubFolder\LastFolder\SomeFile.txt”吗?
  • 是的,感谢您指出我的错误!
  • 你需要改写这个。我读了两遍,我仍然不确定你真正想要什么。否则,我很想回答:使用 IndexOf 和 Substring 方法来获取路径的第二部分(或删除路径的第一部分)——我觉得这不是你想要的。查看 System.IO.Path 类的静态方法 - 它有一些用于组合路径和类似方法的好帮手。
  • 这是我想要的。但是,我宁愿避免字符串操作。如果可能的话,内置的框架方式会更好。
  • 这能回答你的问题吗? How to get relative path from absolute path

标签: c# .net path


【解决方案1】:

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

在以下 git 存储库中搜索 makeRelativehttps://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;
}

【讨论】:

  • 抱歉,这似乎不起作用makeRelative(@"F:\a\b", @"F:\") 例如返回..\b(而不是a\b
  • 你能再试一次 - 我已经更新了我的最新版本吗?如果它不起作用,我会修复它。
  • 提供完整代码,不要只做链接回答。代码已更改,您的链接指向代码的另一部分。
【解决方案2】:

是的,你可以这样做,这很简单,将路径视为 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"

【讨论】:

  • relPath = Uri.UnescapeDataString(relPath) 修复空格。
  • 如果根路径不以“\”结尾,则不会从完整路径中删除根路径的最后一部分!
  • 此外,您的最终结果将是目录分隔符设置为正斜杠,这在大多数情况下是 Windows 中的意外行为,但并不总是有问题。
【解决方案3】:

在您的示例中,它只是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"

【讨论】:

  • 或“去掉以斜线结尾的最长公共前缀”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
相关资源
最近更新 更多