这种制作相对路径的方法有效吗?

发布于 2024-11-13 12:06:19 字数 712 浏览 1 评论 0原文

由于 .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);
}

这个版本似乎可以工作,但它让我感到有点疑问:是否有任何有效的本地文件系统路径可能会被这种无端的转义破坏?

相关: 如何从绝对路径获取相对路径路径 该问题的答案根本没有解决异常字符和转义的问题,因此也没有回答这个问题。

Since .NET doesn't include an API to make relative paths, I've used Uri's MakeRelativeUri method instead. This works, but I've encountered several cases in which it doesn't due to the fact the Uri is escaped. So I've patched up that too:

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

This versions seems to work, but it leaves me feeling a little quesy: aren't there any valid local filesystem paths that this gratuitous unescaping might corrupt?

Related: How to get relative path from absolute path
The answers to that question do not address the issue of unusual characters and escaping at all, and as such don't answer this question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小鸟爱天空丶 2024-11-20 12:06:19

您可以只使用 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\            ..\..\

Instead of escaping, unescaping and replacing, you could just use the underlying algorithm used by System.Uri and the PathDifference method. Here it is, recovered via Reflector and modified for slightly better readability. It has also been modified to use backslashes for DOS-style paths instead of forward slashes for URIs, and the comparison is always case-insensitive.

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

The expectation for the inputs seems to be that if either path represents a directory, it must have a trailing backslash. Obviously, the paths must be non-null as well.

Here are some example inputs and outputs... see if it meets your needs.

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\            ..\..\
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文