30

刚遇到一个有趣的案例。

我的软件报告了由于路径长于 MAX_PATH 导致的故障。

该路径只是“我的文档”中的一个普通旧文档,例如:

C:\Documents and Settings\Bill\Some Stupid FOlder Name\A really ridiculously long file thats really very very very..........very long.pdf

总长度 269 个字符 (MAX_PATH==260)。

用户没有使用外部硬盘驱动器或类似的东西。这是 Windows 托管驱动器上的文件。

所以我的问题是这个。我应该关心吗?

我不是说我可以处理长路径,我问我是否应该。是的,我知道某些 Win32 API 上的“\?\”unicode hack,但似乎这种 hack 并非没有风险(如它正在改变 API 解析路径的方式),并且并非所有 API 都支持。

所以无论如何,让我陈述我的立场/主张:

  1. 首先,用户能够打破这个限制的唯一方法可能是她使用的应用程序使用了特殊的 Unicode hack。这是一个 PDF 文件,所以她使用的 PDF 工具可能使用了这个 hack。
  2. 我试图重现这一点(通过使用 unicode hack)并进行了实验。我发现虽然该文件出现在资源管理器中,但我对此无能为力。我无法打开它,我无法选择“属性”(Windows 7)。其他常用应用程序无法打开该文件(例如 IE、Firefox、记事本)。Explorer 也不会让我创建太长的文件/目录 - 它只是拒绝。命令行工具 cmd.exe 同上。

所以基本上,人们可以这样看:rouge 工具允许用户创建许多 Windows(例如资源管理器)无法访问的文件。我可以认为我不应该处理这个问题。

(顺便说一句,这不是对短最大路径长度的投票:我认为 260 个字符是个笑话,我只是说如果 Windows shell 和某些 API 不能处理 > 260 那么我为什么要?)。

那么,这是一个公平的观点吗?我应该说“不是我的问题”吗?

更新:刚刚有另一个用户有同样的问题。这次是一个 mp3 文件。我错过了什么吗?这些用户如何创建违反 MAX_PATH 规则的文件?

4

8 回答 8

11

这不是一个真正的问题。NTFS 支持的文件名最大为32K32,767 个宽字符)。您只需要使用正确的 API 和正确的文件名语法。基本规则是:文件名应该以'\\?\'(参见http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx)开头,例如\\?\C:\Temp. 您可以在 UNC: 中使用相同的语法\\?\UNC\Server\share\Path。重要的是要了解您只能使用 API 函数的一小部分。例如查看 MSDN 功能描述

CreateFile
CreateDirectory 
MoveFile

等等

你会发现这样的文字:

在此函数的 ANSI 版本中,名称仅限于 MAX_PATH 字符。要将此限制扩展到 32,767 个宽字符,请调用函数的 Unicode 版本并在路径前添加“\?\”。有关详细信息,请参阅命名文件。

这个功能你可以放心使用。如果您有一个文件句柄,则可以不受任何限制CreateFile地使用所有其他使用的函数hFileReadFile等)。WriteFile

如果您编写程序,例如病毒扫描程序或备份软件或在服务器上运行的一些好软件,您应该编写程序,以便所有文件操作都支持最多32K字符的文件名,而不是MAX_PATH字符。

于 2010-05-13T10:05:49.967 回答
10

许多用 C 或 C++ 编写的软件都存在这种限制。包括 MSFT 代码,尽管他们一直在削减它。它只是部分 Win32 限制,例如通过 WIN32_FIND_DATA 对文件名(而不是路径)的长度有硬性上限。甚至 .NET 也有长度限制的原因之一。这不会很快消失,Win32 仍然很强大,石器时代的 C 弦也不会消失。

毫无疑问,您的客户可能对它没有什么同情心,可能直到您向他们展示另一个以同样方式失败的程序。但是,请确保您的代码能够可靠地检测到潜在的字符串缓冲区溢出,然后进行合理的诊断。对轰炸堆损坏的程序没有同情心。

于 2010-05-13T11:57:03.390 回答
6

正如您所提到的,许多 Windows Shell 函数仅适用于 MAX_PATH 的路径。在嵌套具有长文件名的目录时,Windows XP 和我相信 Vista 在资源管理器中都存在问题。我没有检查过 Windows 7 - 也许他们已经解决了这个问题。不幸的是,这意味着用户很难浏览这些文件。

如果您真的希望支持长路径,则需要检查您在 Shell32.dll 中使用的任何函数,这些函数采用路径以确保它们支持长路径。对于那些不使用的人,您必须使用 Kernel32 函数自己编写它们。

如果您决定使用 Shell32 并限制为 MAX_PATH,则建议您编写代码以支持长文件路径。如果 Microsoft 以后更改 Shell32(或创建替代方案),您将能够更好地添加对它们的支持。

只是为了给问题添加另外几个维度,请记住文件名是 UTF-16,您可能会遇到可能区分大小写的非 NTFS 或 FAT 文件系统!

于 2010-05-14T02:13:24.477 回答
5

您自己的 API 不应硬编码路径长度的固定限制(或任何其他硬限制);但是,您不应该为了完成某些任务而违反系统 API 的先决条件。恕我直言,Windows 限制路径名长度的事实是荒谬的,应该被视为一个错误。也就是说,不,我建议您不要尝试使用除文档之外的各种系统 API,即使这会导致某些不良行为,例如限制最大路径长度。所以,简而言之,你的观点是完全公平的;如果操作系统不支持它,那么操作系统不支持它。也就是说,您可能希望向用户说明这是 Windows 的限制,而不是您自己的代码的限制。

于 2010-05-13T09:54:07.910 回答
2

即使是不支持超过 MAX_PATH 的路径的软件也可以创建这些具有长路径的文件的一种简单方法:通过文件共享。

例子:

“C:\My veeeeeeeeeeeeeeeeeeeee looooooooooooooooooong 文件夹”可以共享为“数据”。然后,假设 M: 映射到 \\computer\data,用户可以通过 UNC 路径 \\computer\data 或(甚至更短)通过驱动器号 (M:\) 访问该文件夹。

这通常发生在文件服务器上。

于 2011-01-12T12:39:59.823 回答
1

路径通常可以大于 260,一个例子是当符号链接被嵌套并且有时甚至是故意重复时。我认为程序员应该考虑他们是否希望他们的程序处理这些疯狂的大路径。IMO,260 有足够的空间,但那只是我。我对此的回答是:

如果您必须如此深入地问自己是否要打破 260 字符的限制,那么这可能就是您应该做的。当我们即将做一些我们不确定的事情时,我们经常寻求确认......

我认为 API 中任何地方的最大路径大约是 32k 长,但这取决于你。回到过去,这是一个相当大的变化(整个内存段的一半!天哪!)但现在,在我们生活的段透明寻址环境中,所有内存都堆放在 32k 的平面上没什么……除非您使用一些需要大量其他字符等的花哨的 unicode 语言,否则 AFAIK 路径不需要那么长。我们可以整天谈论这个,但您明白了。我希望这有帮助......还是伤害?

于 2012-09-25T04:26:25.593 回答
1

我正在做一些 C 编程,我正在寻找一种方法来获取给定文件名的最大长度,在搜索 MAX_PATH 之后,我偶然发现了这个线程,在对这个问题进行了一些思考之后,在阅读了关于这个线程的评论之后,我有得出以下结论。

所以我知道 NTFS 支持最长 32.767 个字符的文件名,但是,根据知识 FAT16 只支持 11 个字符的文件名,8 + 3,所以实际上操作系统应该有一个函数,我们的程序可以调用它来确定最大文件名大小,仅仅是因为所有文件系统都有不同的限制,包括文件名的长度。

所以最终的结论必须是,由于我们,开发人员,不知道数据将存储在哪个文件系统中,因此唯一的解决方案必须是尝试和错误的方法。

于 2013-07-07T17:48:38.260 回答
0

严格来说不是对您的具体问题的回答,但它可能会帮助那些确实需要处理长文件名的人。

Delimon 库是 Microsoft TechNet 上基于 .NET Framework 4 的库,用于克服长文件名问题:

Delimon.Win32.IO 库 (V4.0)

它有自己的 System.IO 中的关键方法版本。例如,您将替换:

System.IO.Directory.GetFiles

Delimon.Win32.IO.Directory.GetFiles

这将让您处理长文件和文件夹。

从网站:

Delimon.Win32.IO 取代了 System.IO 的基本文件功能,并支持多达 32,767 个字符的文件和文件夹名称。

这个库是在 .NET Framework 4.0 上编写的,可以在 x86 和 x64 系统上使用。标准 System.IO 命名空间的文件和文件夹限制可以处理文件名中包含 260 个字符和文件夹名称中包含 240 个字符的文件(MAX_PATH 通常配置为 260 个字符)。通常,您会在使用标准 .NET 库时遇到 System.IO.PathTooLongException 错误。

于 2013-02-16T06:15:02.437 回答