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

Windows NTFS中的文件名存储为什么编码?,windows,unicode,ntfs,Windows,Unicode,Ntfs,我刚刚开始编写一些程序,在WinXP系统上处理具有非英语名称的文件名。我已经做了一些关于unicode的推荐阅读,我想我已经了解了基本的想法,但是有些部分对我来说还不是很清楚 具体来说,NTFS中存储的文件名(不是内容,而是文件的实际名称)是什么编码(UTF-8、UTF-16LE/BE)?是否可以使用fopen()打开任何文件,该文件使用char*,或者我别无选择,只能使用wfopen(),该文件使用wchar\u t*,并且可能需要UTF-16字符串 我尝试手动将UTF-8编码的字符串输入到f

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

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

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

unsigned char filename[]={0xEA,0xB0,0x80,0x2E,0x74,0x78,0x74,0x0};//가.文本
FILE*f=fopen((char*)文件名,“wb+”;
但这个结果被称为“ê°€.txt”

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


有人能解释一下吗?

NTFS将文件名存储在UTF-16中,但是
fopen
使用的是ANSI(而不是UTF-8)

为了使用UTF16编码的文件名,您需要使用文件open调用的Unicode版本。为此,请在项目中定义
UNICODE
\u UNICODE
。然后使用
CreateFile
调用或
wfopen
调用。

fopen()-在windows上的MSVC中(默认情况下)不接受utf-8编码字符*

不幸的是,utf-8是在最近的伟大计划中发明的。Windows API分为Unicode和Ansi版本。每个接受或处理字符串的windows api实际上都有一个W或后缀-W表示“宽”字符/Unicode,一个表示Ansi。宏魔术对开发人员隐藏了所有这些,因此您只需根据构建配置使用char*或wchar\u t*调用CreateFile,而不知道它们之间的区别

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

现在,由于c运行时函数(如fopen)需要在默认情况下工作,而不需要开发人员知道,因此在windows系统上,它们希望在windows本地编码中接收字符串。msdn指出microsoft c-runtime api setlocal可以更改当前线程的区域设置,但特别指出,对于每个字符需要超过2字节的任何区域设置(如utf-8),它都将失败


因此,在Windows上没有快捷方式。您需要使用wfopen或原生API CreateFileW(或使用Unicode构建设置创建项目,只需调用Createfile)和wchar\u t*字符串。

如其他人所回答,处理UTF-8编码字符串的最佳方法是将其转换为UTF-16,并使用本机Unicode API,如
\wOpen
CreateFileW

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

  • 使用将UTF-8表示转换为UTF-16

  • 用于获取仅为ASCII的“短路径”
    GetShortPathNameW
    将返回一个包含所有ASCII内容的宽字符串,您需要通过无损复制将其转换为一个窄字符串,每个
    wchar\u t
    char

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


  • 虽然这并非推荐的长期策略,但由于Windows短路径是每个卷都可以关闭的传统功能,因此它可能是将文件名传递给使用
    fopen()
    和其他文件相关API调用的代码的唯一方法(
    stat
    access
    、ANSI版本的
    CreateFile
    和类似版本)。

    如果将项目更改为使用UNICODE定义的构建太大,则可以调用
    wfopen()
    CreateFileW()
    在非unicode版本中。鉴于Windows NT和NTFS比UTF-16标准旧,是否可能改用旧的UCS-2?NTFS允许名称编码使用除0x0000以外的任何16位值序列。这意味着支持UTF-16代码点,但文件系统不检查序列是否有效UTF-16。[]@hillu Win32 Unicode函数使用
    wchar\u t
    字符串。NT和NTFS可能早于UTF-16,但
    wchar\u t
    可用于Windows上的UCS-2和UTF-16,Microsoft从UCS-2迁移到Win2K以后的版本中使用UTF-16。实际上,有一个快捷方式:您可以将UTF-8字符串转换为Unicode,只创建ASCII使用“短路径名”,并将其传递给
    fopen
    。这是将非ASCII文件名传递给仅使用
    fopen
    打开文件的旧式库(或用便携式C编写的库)的唯一方法。每个接收或处理字符串的windows api实际上都带有W或后缀-W,表示“宽”字符/Unicode和用于Ansi的"-大多数函数,但不是所有函数。已经存在很长时间的函数,特别是追溯到早期Windows基于ANSI的时候,当然会存在。但近年来引入的新函数,以及以后的新函数,往往只有较宽的版本,并且没有W后缀。Microsoft希望逐步淘汰ANSI。太棒了,你谢谢你,谢谢你