【问题标题】:Normalize file path with WinAPI [duplicate]使用 WinAPI 规范化文件路径 [重复]
【发布时间】:2010-10-15 15:24:56
【问题描述】:

可能重复:
Best way to determine if two path reference to same file in C/C++

给定两个可能不同大小写和斜杠的文件路径字符串('\''/'),是否有一种快速方法(不涉及编写我自己的函数)将两个路径标准化为相同的形式,或者在至少要测试它们的等效性?

我仅限于 WinAPI 和标准 C++。所有文件都是本地文件。

【问题讨论】:

    标签: c++ c windows winapi path


    【解决方案1】:

    我可以推荐PathCanonicalize吗?

    【讨论】:

    • 它看起来不像是针对连接点或 UNC 路径的地址......但它看起来确实很有用。
    • 这就是我一直在寻找的方法。不是 GetFullPathName。
    • 查看此答案后,我尝试使用 PathCanonicalize() 并发现它已严重损坏。 PathCanonicalize("../foo.txt") 总是返回 /foo.txt! PathCanonicalize() 只是对字符串进行微不足道的编辑,上面的损坏是记录在案的行为。无用。我将用我发现的内容发布另一个答案。
    • 为什么要麻烦处理连接点?这是由对象管理器完成的。
    【解决方案2】:

    我找到了一篇博客文章,其中包含我所见过的解决此问题的最彻底、甚至最详尽的功能。它可以处理任何事情,甚至是像V:foo.txt 这样可怕的极端情况,您使用subst 命令将V: 映射到Z:,但您已经使用substZ: 映射到其他驱动器;它循环直到所有subst 命令都被解除。网址:

    http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html

    我的项目是纯 C 代码,而那个函数是 C++。我开始翻译它,但后来我发现我可以通过一个函数调用获得我想要的规范化路径:GetLongPathName()。这不会处理可怕的极端情况,但它可以满足我的迫切需求。

    我发现GetLongPathName("foo.txt") 只是返回foo.txt,但只是通过在文件名前面加上./ 我得到了规范化形式的扩展:

    GetLongPathName("./foo.txt"),如果在目录C:\Users\steveha中执行,则返回C:\Users\steveha\foo.txt

    所以,在伪代码中:

    如果路径名的第二个字符是 ':' 或第一个字符是 '/' 或 '\',只需调用 GetLongPathName() 否则,将“./”复制到临时缓冲区,然后将文件名复制到临时缓冲区 + 2,以获取前缀为“./”的文件名的副本,然后调用 GetLongPathName()。

    【讨论】:

    • 好吧,至少那篇文章提供的代码看起来像是完成了所有繁重的工作。它当然可以处理更多的极端情况,并且比您期望的更完整。显然作者已经在这些问题上烧过几次了......您更简单的后备可能对于大多数情况来说已经足够了,并且让奇异的案例被用来欺骗需要欺骗的软件。
    • 我的用户可能从未听说过subst 命令,到目前为止,我的简单 C 代码运行良好。
    • 对我们老前辈来说最大的惊喜是subst 仍然存在......它甚至存在于 Win7 64 位,但如果不是更早的话,它可以追溯到 DOS 5.0。 Win7 带有一堆用于向后兼容的 JUNCTIONS。这让我的一些旧的 Perl 脚本在文件系统中游荡,因为它们不是目录,当然也不是文件。一个例子是C:\Documents and Settings 是一个映射到C:\Users 的JUNCTION。
    • 为什么不GetFullPathName()msdn.microsoft.com/en-us/library/windows/desktop/…
    • 我在四年前回答了这个问题,我已经不记得为什么我使用GetLongPathName() 而不是GetFullPathName()。我链接的那篇 2009 年的博客帖子显示了使用 GetFullPathName() 的代码,如果它对那个人来说足够好,我相信这是一个好方法。
    【解决方案3】:

    根据路径是否是相对的、是否包含“..”、连接点或 UNC 路径,这可能比您想象的要困难。最好的方法可能是使用 GetFileInformationByHandle() 函数,如this answer

    编辑:我同意 RBerteig 的评论,即如果路径不指向本地文件,这可能会变得难以实现。任何关于如何安全处理此案例的评论将不胜感激。

    【讨论】:

    • 只要这两个路径解析到同一台计算机上的文件,那么看起来 GetFileInformationByHandle() 就是正确的答案。如果他们解析到不同的计算机,我看不到保证,也看不到获得一台计算机的简单方法。对此进行测试并不一定容易。
    • 就我而言,所有文件都是本地文件,所以这可行。
    • @RBerteig:我也没有一种简单的方法来获得一个。但是我找到了一个非常重要的并将其放在答案中;看一看。即使那个也只是万无一失,但对大多数人来说应该绰绰有余。
    【解决方案4】:

    有一些奇怪的情况。例如,“c:\windows..\data\myfile.txt”与“c:\data.\myfile.txt”和“c:\data\myfile.txt”相同。您可以在其中包含任意数量的“\.\”和“\..\”。您可能会查看 Windows API 函数 GetFullPathName。它可能会为您进行规范化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-10
      • 2015-07-21
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 2019-10-12
      相关资源
      最近更新 更多