有没有标准的方法来fopen
处理 Unicode 字符串文件路径?
4 回答
不,没有标准的方法。操作系统之间存在一些差异。以下是不同操作系统处理非 ASCII 文件名的方式。
Linux
在 Linux 下,文件名只是一个二进制字符串。大多数现代发行版的约定是对非 ASCII 文件名使用 UTF-8。但在一开始,将文件名编码为 ISO-8859-1 是很常见的。基本上由每个应用程序来选择编码,因此您甚至可以在同一个文件系统上使用不同的编码。LANG
环境变量可以提示您首选的编码是什么。但是现在,您可能到处都可以假设 UTF-8。
但是,这并非没有问题,因为包含无效 UTF-8 序列的文件名在大多数 Linux 文件系统上完全有效。如果您只支持 UTF-8,您将如何指定这样的文件名?理想情况下,您应该同时支持 UTF-8 和二进制文件名。
操作系统
OS X 上的 HFS 文件系统在内部使用 Unicode (UTF-16) 文件名。大多数 C(和 POSIX)库函数都fopen
接受 UTF-8 字符串(因为它们是 8 位兼容的)并在内部进行转换。
视窗
Windows API 使用 UTF-16 作为文件名,但fopen
使用当前代码页,不管是什么(UTF-8 刚刚成为一个选项)。wchar_t
许多 C 库函数具有接受 UTF-16(在 Windows 上)的非标准等效项。例如,_wfopen
代替fopen
.
这是您当前语言环境的问题。在我启用了 unicode 的系统上,文件路径将使用 unicode。我可以通过 locale 命令检测到这一点:
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
文件路径的编码通常在系统范围内设置,因此如果您的文件路径不在系统的区域设置中,您可能需要通过iconv库对其进行转换。
现在几乎所有的 POSIX 平台都使用 UTF-8。而且现代 Windows 也支持 UTF-8 作为语言环境,您可以在任何地方使用 UTF-8 并打开任何文件,而无需在 Windows 上使用宽字符串。fopen
只是便携式工作
setlocale(LC_ALL, "en_us.utf8"); // need some setup before calling this
fopen(R"(C:\filê\wíth\Ünicode\name.txt)", "w+");
从 Windows 10 build 17134(2018 年 4 月更新)开始,通用 C 运行时支持使用 UTF-8 代码页。这意味着
char
传递给 C 运行时函数的字符串将需要 UTF-8 编码的字符串。要启用 UTF-8 模式,".UTF8"
请在使用setlocale
. 例如,setlocale(LC_ALL, ".UTF8")
将使用当前默认的 Windows ANSI 代码页 (ACP) 作为语言环境,使用 UTF-8 作为代码页。...
要在 Windows 10 之前的操作系统(例如 Windows 7)上使用此功能,您必须使用应用程序本地部署或使用 Windows SDK 版本 17134 或更高版本进行静态链接。对于 17134 之前的 Windows 10 操作系统,仅支持静态链接。