如何在Windows应用程序中将相对路径转换为绝对路径?

104

如何在Windows应用程序中将相对路径转换为绝对路径?

我知道在ASP.NET中可以使用server.MapPath()。但是在Windows应用程序中我们该怎么办呢?

我的意思是,如果有一个.NET内置函数可以处理这个问题的话...


2
你是指相对于当前目录的相对路径,换句话说是工作目录,还是相对于.exe文件的位置? - Tobias Hertkorn
2
有两种相对路径。一种是形如“A\B\C”的形式,不涉及特定的基础路径。另一种是形如“.\A\B”或“..\A\B”的形式;它们是相对于当前工作目录的。 - MSalters
1
@Amit Dhall:顺便说一下,接受并点赞帮助你的答案是一件好事。 - Francis B.
5个回答

206

你尝试过:

string absolute = Path.GetFullPath(relative);

请注意,这将使用进程的当前工作目录,而不是包含可执行文件的目录。如果这并没有帮助到您,请澄清您的问题。


5
这不是取决于您从哪里启动应用程序,而不是exe文件所在的位置吗?尽管问题并不是非常清楚。 - Tobias Hertkorn
1
就像你所说的,这个问题不够清晰。GetFullPath将从当前工作目录解析。我会编辑我的回答来表明这一点。 - Jon Skeet
1
如果通过Windows资源管理器启动应用程序,当前目录和执行程序集目录似乎是相同的(至少在采取措施使它们不同之前是这样)。即使您使用指向完全不同位置的可执行文件的快捷方式,这也是正确的。 - H2ONaCl

20

如果您想获取相对于您的 .exe 文件的路径,则使用以下方法

string absolute = Path.Combine(Application.ExecutablePath, relative);

4
请注意使用Path.Combine方法。如果“相对路径”部分以斜杠开头,则它可能不会按照你预期的方式工作。 - Noon Silk
2
@silky:那么,它就不是相对的了,对吧? - Tor Haugen
1
似乎 Path.Combine 甚至不能处理驱动器相对路径。它似乎忽略了初始路径。我将发布我的完整解决方案。 - Nyerguds
3
这个程序无法处理相对路径。它只接受一个目录和一个文件名。如果第二个参数以类似于 .. 的任何字符开头,它将产生垃圾数据。 - Jonathan Wood
1
@JonathanWood 实际上,所有在 .Net 中的文件操作系统都可以完美接受和解决包含 .. 的路径。如果这让你感到困扰,可以执行 absolute = Path.GetFullPath(absolute) 来解决它。 - Nyerguds
显示剩余2条评论

17

这个方法适用于不同驱动器的路径,驱动器相对路径和实际相对路径。甚至,如果basePath实际上不是绝对路径,它也可以工作;它总是使用当前工作目录作为最终备选项。

public static String GetAbsolutePath(String path)
{
    return GetAbsolutePath(null, path);
}

public static String GetAbsolutePath(String basePath, String path)
{
    if (path == null)
        return null;
    if (basePath == null)
        basePath = Path.GetFullPath("."); // quick way of getting current working directory
    else
        basePath = GetAbsolutePath(null, basePath); // to be REALLY sure ;)
    String finalPath;
    // specific for windows paths starting on \ - they need the drive added to them.
    // I constructed this piece like this for possible Mono support.
    if (!Path.IsPathRooted(path) || "\\".Equals(Path.GetPathRoot(path)))
    {
        if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
            finalPath = Path.Combine(Path.GetPathRoot(basePath), path.TrimStart(Path.DirectorySeparatorChar));
        else
            finalPath = Path.Combine(basePath, path);
    }
    else
        finalPath = path;
    // resolves any internal "..\" to get the true full path.
    return Path.GetFullPath(finalPath);
}

1
这是一个很好的解决方案,因为它根据基本路径组合绝对或相对路径。在我看来,relativePath 参数应该重命名为 AbsoluteOrRelativePath,因为这才是它真正代表的意思。谢谢。 - Julio Nobre
1
如果已经是绝对路径,那只是一个特殊情况...这个函数仍然旨在解析相对路径,哈哈。我只是在这里给它命名,以便清楚哪个参数是哪个 ;) - Nyerguds
1
@JulioNobre 特别是因为这里的参数与 Path.Combine 相比是反向的。虽然很容易修复,但我避免这样做,因为我经常使用它来解析工作目录上的相对路径,并且将 null 作为第一个参数看起来很奇怪。 - Nyerguds
1
我很感谢您的建议,但我只打算在需要将基本路径与可能相对于该基本路径或绝对路径的另一个路径组合时使用此帮助程序。这就是为什么我更喜欢采用以下签名:GetAbsolutePath(String BasePath,String RelativeOrAbsolutePath)。如果某个参数为空,则会引发异常以强制执行必须使用此方法的两个参数。再次感谢 :-) - Julio Nobre
2
是的,那很明智。但我懒得编辑这个程序只为了调整一些参数。 - Nyerguds
显示剩余4条评论

1

这是一个有些老的话题,但对某些人可能会有用处。 我解决了一个类似的问题,但在我的情况下,路径不在文本开头。

所以这是我的解决方案:

public static class StringExtension
{
    private const string parentSymbol = "..\\";
    private const string absoluteSymbol = ".\\";
    public static String AbsolutePath(this string relativePath)
    {
        string replacePath = AppDomain.CurrentDomain.BaseDirectory;
        int parentStart = relativePath.IndexOf(parentSymbol);
        int absoluteStart = relativePath.IndexOf(absoluteSymbol);
        if (parentStart >= 0)
        {
            int parentLength = 0;
            while (relativePath.Substring(parentStart + parentLength).Contains(parentSymbol))
            {
                replacePath = new DirectoryInfo(replacePath).Parent.FullName;
                parentLength = parentLength + parentSymbol.Length;
            };
            relativePath = relativePath.Replace(relativePath.Substring(parentStart, parentLength), string.Format("{0}\\", replacePath));
        }
        else if (absoluteStart >= 0)
        {
            relativePath = relativePath.Replace(".\\", replacePath);
        }
        return relativePath;
    }
}

例子:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;

1
嗯,你正在重新发明轮子。Path.GetFullPath会自动解析.\和..\。此外,你正在一般性地向String类添加AbsolutePath扩展函数...可能有点过度设计了。 - Nyerguds
1
我说Path.GetFullPath总是将基目录视为应用程序的AppDomain的当前目录,这样情况下,Path.GetFullPath无法从不同的目录返回完整路径。然而,以下算法考虑到了这一点...我的意思是,你只需要添加另一个可选参数,它将替换CurrentDomainDirectory。 - Samuel

0

Windows 10 Python 3.8:类型对象“Path”没有属性“GetFullPath”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接