在Windows上使用zlib和Unicode文件路径

Joh*_*åde 8 c unicode zlib

我正在使用zlib阅读gzip压缩文件.然后使用打开文件

gzFile gzopen(const char *filepath, const char *mode);
Run Code Online (Sandbox Code Playgroud)

如何处理存储const wchar_t*在Windows上的Unicode文件路径?

在类UNIX平台上,您只需将文件路径转换为UTF-8并调用gzopen(),但这在Windows上无效.

Mar*_*ler 13

下一版本的zlib将包含此函数,其中_WIN32#defined:

gzFile gzopen_w(const wchar_t *path, char *mode);

它的工作原理完全像gzopen(),除了它使用_wopen()而不是open().

我故意没有复制第二个参数_wfopen(),因此我没有调用它_wgzopen()来避免可能与该函数的参数混淆.因此这个名字gzopen_w().这也避免了使用C保留的名称空间.

  • 最好的答案。你问如何做,库的作者带来了一个新功能。 (2认同)

dan*_*n04 11

首先,什么文件名?

在类Unix系统上

文件名是以零结尾的字节序列.内核不需要关心字符编码(除了知道ASCII代码/).

但是,从用户的角度来看,将文件名解释为字符序列更方便,这可以通过指定为语言环境一部分的字符编码来完成. 通过使UTF-8语言环境可用来支持Unicode.

在C程序中,文件用普通char*字符串表示,如fopen. POSIX API没有宽字符版本. 如果您有wchar_t*文件名,则必须将其显式转换为char*.

在Windows NT上

文件名是UTF-16代码单元的序列.实际上,Windows中的所有字符串操作都是在内部以UTF-16完成的.

所有Microsoft的C(++)库(包括Visual C++运行时库)都使用char*字符串在特定于语言环境的旧"ANSI"代码页中的约定,字符串使用wchar_t*UTF-16.这些char*函数只是围绕新wchar_t*函数的向后兼容包装器.

所以,如果你打电话MessageBoxA(hwnd, text, caption, type),这与打电话基本相同MessageBoxW(hwnd, ToUTF16(text), ToUTF16(caption), type).当你打电话时fopen(filename, mode),就像_wfopen(ToUTF16(filename), ToUTF16(mode)).

请注意,这_wfopen用于处理wchar_t*字符串许多非标准C函数之一.这不仅仅是为了方便; 不能使用标准char*等效项,因为它们将您限制为"ANSI"代码页(不能是UTF-8).例如,在windows-1252语言环境中,您不能(轻松)fopen该文件????.c,因为无法在窄字符串中表示这些字符.

在跨平台库中

一些典型的方法是:

  1. 将标准C函数与char*字符串一起使用,并且不要在Windows上提供对非ANSI字符的支持.
  2. 使用char*字符串但将其解释为UTF-8而不是ANSI.在Windows上,编写包含UTF-8参数的包装函数,将它们转换为UTF-16,并调用函数_wfopen.
  3. 在任何地方使用宽字符串,除了需要为非 Windows系统编写包装函数之外,它类似于#2 .

zlib如何处理文件名?

不幸的是,它似乎使用上面的天真方法#1,open而不是_wopen直接使用(而不是).

你怎么解决它?

除了已经提到的解决方案(我最喜欢的是Appleman1234的gzdopen建议)之外,你可以利用符号链接为文件提供一个替代的全ASCII名称,然后你可以安全地传递给它gzopen.如果文件已经有合适的短名称,您甚至可能不必这样做.

  • 所以zlib有两种方法。要么 a) 让 gzopen() 始终在 Windows 上进行 UTF-8 到 UTF-16 转换并使用 _wopen(),或者 b) 保留 gzopen() 使用 open(),并仅添加新的 _wgzopen() 函数采用 UTF-16 参数并使用 _wopen() 的 Windows。dan04 的推荐是什么? (2认同)
  • 好的。所以我可以两者兼得。gzopen() 可以从 UTF-8 转换为 UTF-16 并在 Windows 中编译时调用 _wopen。也可能有一个 _wgzopen() 使用 UTF-16 作为输入(对于两个参数?)。我没有得到整个“委托给现有的语言环境感知功能”的东西。这是否意味着从 UTF-8 转换为 UTF-16 的例程不是“语言环境感知”?顺便问一下,那是什么套路? (2认同)