NTFS中的文件名是以什么编码存储的?
我刚开始使用一些编程来处理WinXP系统上非英文名称的文件名。 我已经做了一些关于unicode的推荐阅读,我想我已经有了基本的想法,但是有些部分对我来说还不是很清楚。
具体来说,什么编码(UTF-8,UTF-16LE / BE)是存储在NTFS中的文件名 (不是内容,而是文件的实际名称)? 是否有可能打开任何文件使用fopen(),这需要一个字符*,或者我别无select,只能使用wfopen(),它使用wchar_t *,大概需要一个UTF-16string?
我尝试手动喂养一个UTF-8编码的stringfopen(),例如。
unsigned char filename[] = {0xEA, 0xB0, 0x80, 0x2E, 0x74, 0x78, 0x74, 0x0}; // 가.txt FILE* f = fopen((char*)filename, "wb+");
但是这是作为'ê°€.txt'出来的。
我的印象(这可能是错误的),一个UTF8编码的string就足以打开Windows下的任何文件名,因为我似乎隐约记得一些Windows应用程序传递(char *),而不是(wchar_t *),并有没问题。
任何人都可以点亮这个?
NTFS以UTF16存储文件名,但fopen使用ANSI(不是utf8)。
为了使用UTF16编码的文件名,您将需要使用文件打开调用的Unicode版本。 通过在你的项目中定义UNICODE和_UNICODE来做到这一点。 然后使用CreateFile调用或wfopen调用。
fopen() – 在Windows上的MSVC不(默认情况下)采取utf-8编码的char *。
不幸的是,utf-8是最近发明的伟大的计划。 Windows API分为Unicode和Ansi版本。 每个使用或处理string的api实际上都有一个W或A后缀,W代表“宽”字符/ Unicode和A代表Ansi。 macros魔法隐藏了所有这些开发者,所以你只需要调用CreateFile或者char *或者wchar_t *,这取决于你的构buildconfiguration而不知道区别。
“Ansi”编码实际上并不是特定的编码: – 但意味着用于“char”string的编码特定于PC的区域设置。
现在,因为c-runtime函数(如fopen)需要在没有开发人员知识的情况下默认工作,所以在windows系统上,他们期望在windows本地编码中接收它们的string。 msdn表示microsoft c-runtime api setlocal可以更改当前线程的语言环境,但是明确地说,对于每个字符需要多于2个字节的任何语言环境(比如utf-8),它将会失败。
所以,在Windows上没有捷径。 你需要用wchar_t *string来使用wfopen或者本地API CreateFileW(或者使用Unicode构build设置来创build你的项目,并且只需调用Createfile)。
正如其他人所回答的,处理UTF-8编码string的最佳方法是将它们转换为Unicode,并使用本机Unicode API(如_wfopen
或CreateFileW
。
然而,这种方法在无条件地调用使用fopen()
库时无济于事,因为它们不支持Unicode,或者因为它们是用可移植C编写的。在这种情况下,仍然可以使用传统的“短path”将UTF-8编码的string转换成可与fopen
使用的ASCII格式,但需要一些操作:
-
使用
MultiByteToWideChar
将UTF-8表示转换为UTF-16。 -
使用
GetShortPathNameW
来获得一个“短path”,这是只有ASCII。GetShortPathNameW
会将它作为一个带有全ASCII内容的宽string返回,您需要通过每个wchar_t
char
的无损拷贝来简单地将其转换为一个窄string。 -
将短path传递给
fopen()
或最终使用fopen()
的代码。 请注意,由该代码打印的错误消息(如果有的话)将引用难看的“短path”(例如kinto-un-筋斗雲
而不是kinto-un-筋斗雲
)。
虽然这不完全是推荐的长期策略,但由于Windows短path是可按卷closures的传统function,因此可能是将文件名传递给使用fopen()
和其他文件types的代码的唯一方法,相关的API调用( stat
, access
,ANSI版本的CreateFile
等)。