在Windows系统中如何获取目录分隔符?('\', '/',等)

22

简而言之:如何询问 Windows 当前系统中的目录分隔符?


不同版本的 Windows 表现不同(例如,在英文版本中 \/ 都起作用,在日语版本中是 ¥,在韩语版本中是 ₩ 等等)。

是否有任何方法可以避免硬编码,而是在运行时询问 Windows?

注意:

理想情况下,解决方案应该不依赖于高级 DLL,比如 ShlWAPI.dll,因为较低级别的库也依赖于此。所以它实际上应该依赖于 kernel32.dllntdll.dll 等…尽管我很难找到任何东西,无论是在高级别还是低级别。

编辑:

一些小实验告诉我,它是 Win32 子系统(即 kernel32.dll…或者是 ntdll.dll 中的 RtlDosPathNameToNtPathName_U 吗?不确定,没有测试...),它将正斜杠转换为反斜杠,而不是内核。(在路径前缀中添加 \\?\ 会使后面无法使用正斜杠--而 NT 原生用户模式 API 在使用正斜杠时也会失败。)

因此,显然它并不完全“内置于” Windows 中,而只是一个兼容性功能--这意味着您不能盲目地替换反斜杠以代替正斜杠,因为任何随机添加 \\?\ 前缀的程序都会自动在正斜杠上出现错误。

关于这个问题我有一些矛盾的感受,但我只是想提一下。

(虽然技术上来说路径分隔符用于分隔路径,而不是目录(;\),但我将其标记为“路径分隔符”。希望人们能够理解我的意思。)


8
分隔符始终相同,即为 0x5c。不同之处在于所使用的代码页用于显示字符。在ANSI代码页中,0x5c是反斜杠。在日语代码页932中,0x5c是日元符号;而在韩文代码页949中,它则是韩元符号。 - vcsjones
1
我同意vcsjones的观点,路径处理的文档提到用反斜杠(0x5c)来分隔目录。实际上,如果你将机器切换到日语环境,按\键会产生¥而不是\。 - Joshua
@vcsjones, Joshua: 我没有意识到那是这种情况,感谢你指出来。然而,我仍然需要一种机制来检测 /(或其他字符)是否是路径分隔符 -- 在Windows 7上似乎是这样的,但在XP上不是,如果可能的话,我宁愿避免硬编码这个规则。 - user541686
3个回答

35
在韩国和日本的Windows版本中,¥字符被显示为目录分隔符号,但它们只是这些Windows版本将相同的Unicode代码点U+005c表示为字形的方式。反斜杠的底层代码点在英语Windows和日语和韩语Windows版本中仍然相同。
可以在此页面上找到有关此额外确认的信息:http://msdn.microsoft.com/en-us/library/dd374047(v=vs.85).aspx

文件名中字符集的安全注意事项

用于日语系统的Windows代码页和OEM字符集包含日元符号(¥)而不是反斜杠(\)。因此,NTFS和FAT文件系统禁止使用日元符号。将Unicode映射到日语代码页时,转换函数将反斜杠(U+005C)和普通的Unicode日元符号(U+00A5)都映射到同一个字符。出于安全原因,您的应用程序通常不应允许在可能被转换用作FAT文件名的Unicode字符串中使用字符U+00A5。

此外,我不知道任何Windows API函数可以获取系统的路径分隔符,但您可以依赖它在所有情况下都是\

http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#naming_conventions

以下基本规则使得应用程序能够创建和处理文件和目录的有效名称,无论文件系统如何:
...
使用反斜杠(\)来分隔路径的组成部分。反斜杠将文件名与其路径以及路径中一个目录名与另一个目录名分开。您不能在实际文件或目录的名称中使用反斜杠,因为它是一个保留字符,将名称分成各个组成部分。
...
关于 / Windows API函数应支持使用/作为目录分隔符,但不一定在命令提示符(command.com)中支持它。
注意:Windows API中的文件I/O函数将“/”转换为“\”,作为将名称转换为NT样式名称的一部分,除非使用以下章节中详细介绍的“\?\”前缀。
这很难弄清楚真相,但这可能是一个关于 Windows 路径中使用 / 的有用链接:http://bytes.com/topic/python/answers/23123-when-did-windows-start-accepting-forward-slash-path-separator

+1 是因为我没有意识到货币符号的问题。然而,我仍然需要一种机制来检测 /(或任何其他字符)是否是路径分隔符——在 Windows 7 上似乎是这样,但在 XP 上不是,如果可能的话,我宁愿避免硬编码此规则。 - user541686
我认为你对XP系统上的正斜杠无法使用是错误的。自从DOS时代起它就一直能用。 - R.. GitHub STOP HELPING ICE
@R..:我不确定你所说的“在操作系统级别”,但请看我的编辑。 - user541686
1
我的意思是当传递给接受路径名的系统API函数时(对于DOS来说,这意味着int 21h)。 - R.. GitHub STOP HELPING ICE
command.com(Windows命令提示符)在/下运行良好(在Windows 7下测试),请参见截图:http://s32.postimg.org/lar69ehp1/Screen_Shot_2016_04_30_at_15_33_30.png - tanguy_k
显示剩余5条评论

4
原帖作者在评论中添加了“内核模式”这个短语,如果原问题的意图是询问内核模式,那么依赖于/作为路径分隔符可能不是一个好主意。不同的文件系统允许在磁盘上使用不同的字符集。Windows中的不同文件系统驱动程序也可以允许不同的字符集,通常不能包括底层文件系统不接受的字符,但有时它们可能会表现出奇怪的行为。例如,Posix模式允许在NTFS分区中的路径名中包含一些组件名称中的字符,即使NTFS通常不允许这些字符。(但显然,在Posix中,/不是其中之一。)
在Unicode内核模式中,U+005C始终是反斜杠,并且始终是路径分隔符。日元和韩元的Unicode代码点不是U+005C,也不是路径分隔符。
在ANSI内核模式中,根据使用的ANSI代码页,会出现一些复杂情况。在与ASCII足够相似的代码页中,0x5C是反斜杠并且是路径分隔符。在ANSI 932和949代码页中,0x5C不是反斜杠,但0x5C可能是路径分隔符,具体取决于它出现的位置。如果0x5C是多字节字符的第一个字节,则它是日元符号或韩元符号,并且是路径分隔符。如果0x5C是多字节字符的第二个字节,则它本身不是字符,因此它既不是日元符号或韩元符号,也不是路径分隔符。你必须从字符串的开头开始解析,才能确定特定字符实际上是否是完整字符。此外,在中文和UTF-8中,多字节字符可能比两个字符更长。

2

标准的斜杠符号 (/) 在所有版本的 DOS 和 Windows 中都可以使用。如果您使用它,就不必担心在日本和韩国版本的 Windows 上如何显示反斜杠的问题,也不必为 Windows 和 POSIX(包括 Mac)的路径分隔符特别处理。只需在任何地方使用正斜杠即可。


问题并不总是关于使用,而是关于解析:例如,如果我得到一个路径,我如何在不知道系统接受的路径分隔符的情况下获取其父目录? - user541686
Windows 没有像 realpath 这样的函数帮你完成这个任务吗? - R.. GitHub STOP HELPING ICE
并不完全准确——有PathCanonicalize和相关的API,但是依赖项(shlwapi.dll)过于高级而实际上并不是非常有用——在内核模式下它是无用的,并且在用户模式下加载了不必要的DLL。更不用说它们甚至不能处理超过260个字符的路径。 - user541686

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