当我们在Linux中调用系统调用,比如`open`,或者调用stdio库函数,比如`fopen`时,需要提供一个`const char * filename`参数。我的问题是这里使用的编码是什么?是UTF-8还是ASCII或ISO8859-X?这取决于系统或环境设置吗?
我知道在MS Windows中有一个名为`_wopen`的函数可以接受UTF-16编码。
我知道在MS Windows中有一个名为`_wopen`的函数可以接受UTF-16编码。
这是一个字节字符串,具体的解释取决于特定的文件系统。
这取决于系统语言环境。查看“locale”命令的输出。如果变量以UTF-8结尾,则您的语言环境为UTF-8。大多数现代Linux系统都将使用UTF-8。尽管安德鲁正确地指出了它实际上只是一个字节字符串,但如果您不匹配系统语言环境,则某些程序可能无法正常工作,并且将无法获得正确的用户输入等。最好坚持使用UTF-8。
open
或fopen
的结果也不取决于用户区域设置。 - n. m.fopen
和所有涉及文件名/路径名的函数的确切字节字符串就是该文件的名称。例如,如果您有一个以 UTF-8 编码为 NFC 的文件名为 ö.txt
的文件,并且您的区域设置(locale)为以 UTF-8 编码并使用 NFC,则可以将其写作 ö.txt
并将其传递给 fopen
。但是,如果您的区域设置基于 Latin-1,则不能传递 Latin-1 形式的 ö.txt
("\xf6.txt"
)到 fopen
并期望它成功;那是一个不同的字节字符串,因此是一个不同的文件名。您需要传递相同的字节字符串作为实际名称: "\xc3\xb6.txt"
(如果将其解释为 Latin-1,则为 "ö.txt"
)。如上所述,这将是一个字节字符串,其解释将开放给底层系统。更具体地说,想象一下C函数;一个在用户空间中,一个在内核空间中,它们都以char *
作为参数。用户空间中的编码取决于用户程序的执行字符集(例如,在gcc中由-fexec-charset=charset
指定)。内核函数期望的编码取决于内核编译期间使用的执行字符集(不确定从哪里获取该信息)。
我对这个话题进行了进一步的调查,并得出结论:unixoid文件系统处理文件名编码的方式有两种不同的方式。
文件名使用“系统语言环境”进行编码,通常情况下可以使用当前环境语言环境反映的 locale
命令(但是可能在全局配置文件中预设)。
文件名以UTF-8编码,独立于任何语言环境设置。
GTK+通过假定UTF-8并允许用当前语言环境编码或用户提供的编码覆盖它来解决此问题。
Qt则通过假定语言环境编码(并且系统语言环境反映在当前语言环境中)并允许使用用户提供的转换函数来解决此问题。
因此,重要的是:默认情况下使用UTF-8或LC_ALL或LANG告诉您的内容,至少为另一种替代方案提供覆盖设置。