NTFS中的文件名是什么编码存储的?

时间:2010-01-12 17:33:31

标签: windows unicode ntfs

我刚刚开始编写一些程序来处理WinXP系统上具有非英文名称的文件名。我已经完成了一些关于unicode的推荐阅读,我认为我得到了基本的想法,但有些部分对我来说仍然不是很清楚。

具体来说,什么编码(UTF-8,UTF-16LE / BE)是存储在NTFS中的文件名称(不是内容,而是文件的实际名称)?是否可以使用fopen()打开任何文件,它接受char *,或者我别无选择,只能使用wfopen(),它使用wchar_t *,并且可能需要UTF-16字符串?

我尝试手动将UTF-8编码的字符串输入fopen(),例如

unsigned char filename[] = {0xEA, 0xB0, 0x80, 0x2E, 0x74, 0x78, 0x74, 0x0}; // 가.txt

FILE* f = fopen((char*)filename, "wb+");

但这是'ê°€.txt'。

我的印象(这可能是错误的)UTF8编码的字符串就足以在Windows下打开任何文件名,因为我似乎依稀记得一些Windows应用程序传递(char *),而不是(wchar_t *) ,并没有任何问题。

任何人都可以对此有所了解吗?

3 个答案:

答案 0 :(得分:36)

NTFS以UTF16格式存储文件名,但fopen使用ANSI(不是utf8)。

要使用UTF16编码的文件名,您需要使用文件打开调用的Unicode版本。通过在项目中定义UNICODE和_UNICODE来完成此操作。然后使用CreateFile调用或wfopen调用。

答案 1 :(得分:14)

fopen() - 在Windows上的MSVC中(默认情况下)不采用utf-8编码的字符*。

不幸的是,utf-8最近才发明在伟大的计划中。 Windows API分为Unicode和Ansi版本。 采用或处理字符串的每个 windows api实际上都带有W或A后缀 - W表示“宽”字符/ Unicode,A表示Ansi。 Macro magic将所有这些隐藏在开发人员之外,因此您只需使用char *或wchar_t *调用CreateFile,具体取决于您的构建配置,而不知道差异。

'Ansi'编码实际上不是特定的编码: - 但意味着用于“char”字符串的编码特定于PC的语言环境设置。

现在,因为c-runtime函数 - 比如fopen - 需要在没有开发人员知识的情况下默认工作 - 在Windows系统上,他们希望在windows本地编码中接收它们的字符串。 msdn表示微软c-runtime api setlocal可以改变当前线程的语言环境 - 但是具体说它对于每个字符需要超过2个字节的任何语言环境都会失败 - 比如utf-8。

因此,在Windows上没有捷径。您需要使用wfopen或本机API CreateFileW(或使用Unicode构建设置创建项目,只需调用Createfile)和wchar_t * strings。

答案 2 :(得分:5)

正如其他人所回答的,处理UTF-8编码字符串的最佳方法是将它们转换为UTF-16并使用本地Unicode API,例如_wfopenCreateFileW

但是,这种方法在调用无条件使用fopen()的库时无效,因为它们不支持Unicode,或者因为它们是用便携式C编写的。在这种情况下,仍然可以使用传统的“短路径”将UTF-8编码的字符串转换为可与fopen一起使用的ASCII格式,但它需要一些工作:

  1. 使用MultiByteToWideChar将UTF-8表示转换为UTF-16。

  2. 使用GetShortPathNameW获取仅限ASCII的“短路径”。 GetShortPathNameW会将其作为带有全ASCII内容的宽字符串返回,您需要通过每个wchar_t char的无损复制转换将其简单地转换为窄字符串。

  3. 将短路径传递给fopen()或最终使用fopen()的代码。请注意,该代码打印的错误消息(如果有)将引用难看的“短路径”(例如KINTO~1而不是kinto-un-筋斗雲)。

  4. 虽然这不是推荐的长期策略,但由于Windows短路径是可以按卷关闭的旧功能,因此可能是将文件名传递给使用{{1}的代码的唯一方法和其他与文件相关的API调用(fopen()stataccess的ANSI版本及类似内容。