概括
如何在 C++ 中使用 libarchive 编写一个 zip 文件,这样路径名将采用 UTF-8 编码?使用 UTF-8 路径名,在使用 OS X / Linux / Windows 8 / 7-Zip / WinZip 时将正确解码特殊字符。
细节
我正在尝试使用 libarchive 编写一个 zip 存档,在 Windows 上使用 Visual C++ 2013 进行编译。
我希望能够将具有非 ASCII 字符的文件(例如 äöü.txt)添加到 zip 存档中。
有四个函数可以在 libarchive 中设置路径名标头:
void archive_entry_set_pathname(struct archive_entry *, const char *);
void archive_entry_copy_pathname(struct archive_entry *, const char *);
void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
不幸的是,它们似乎都不起作用。
特别是,我尝试过:
const char* myUtf8Str = ...
archive_entry_update_pathname_utf8(entry, myUtf8Str);
// this sounded like the most straightforward solution
和
const wchar_t* myUtf16Str = ...
archive_entry_copy_pathname_w(entry, myUtf16Str);
// UTF-16 encoded strings seem to be the default on Windows
在这两种情况下,生成的 zip 存档都无法在 Windows 资源管理器和 7-Zip 中正确显示文件名。
我确信我的输入字符串编码正确,因为我将它们从 QtQString
实例转换为在我的代码的其他部分运行良好:
const char* myUtf8Str = filename.toUtf8().constData();
const wchar_t* myUtf16Str = filename.toStdWString().c_str();
例如,在创建 zip 文件时,这甚至适用于对 libarchive 的另一个调用:
archive_write_open_filename_w(archive, zipFile.toStdWString().c_str());
// creates a zip archive file where the non-ASCII
// chars are encoded correctly, e.g. äöü.zip
我还尝试更改 libarchive 的选项,如下例所示:
archive_write_set_options(a, "hdrcharset=UTF-8");
但是这个调用失败了,所以我假设我必须设置一些其他选项,但是我的想法已经不多了......
更新 2
我已经阅读了有关 zip 格式的更多内容。它允许以 UTF-8 编写文件名,这样 OS X / Linux / Windows 8 / 7-Zip / WinZip 将始终正确解码它们,请参见此处。
这就是我想使用 libarchive 实现的目标,即我想将我的 UTF-8 编码传递给它,pathname
并将其存储在 zip 文件中而不进行任何转换。
我添加了“设置语言环境”方法作为(不满意的)答案。