Val*_*ris 7 c++ zip utf-8 wstring libarchive
摘要
如何在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中有四个函数来设置pathname标头:
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 *);
Run Code Online (Sandbox Code Playgroud)
不幸的是,它们似乎都没有用.
特别是,我试过:
const char* myUtf8Str = ...
archive_entry_update_pathname_utf8(entry, myUtf8Str);
// this sounded like the most straightforward solution
Run Code Online (Sandbox Code Playgroud)
和
const wchar_t* myUtf16Str = ...
archive_entry_copy_pathname_w(entry, myUtf16Str);
// UTF-16 encoded strings seem to be the default on Windows
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,生成的zip存档都不会在Windows资源管理器和7-Zip中正确显示文件名.
我确信我的输入字符串编码正确,因为我从Qt QString实例转换它们在我的代码的其他部分非常有效:
const char* myUtf8Str = filename.toUtf8().constData();
const wchar_t* myUtf16Str = filename.toStdWString().c_str();
Run Code Online (Sandbox Code Playgroud)
例如,在创建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
Run Code Online (Sandbox Code Playgroud)
我也试图改变libarchive的选项,如下例所示:
archive_write_set_options(a, "hdrcharset=UTF-8");
Run Code Online (Sandbox Code Playgroud)
但是这个调用失败了,所以我假设我必须设置一些其他选项,但是我的想法已经用完......
更新2
我已经做了一些关于zip格式的阅读.它允许以UTF-8编写文件名,这样OS X/Linux/Windows 8/7-Zip/WinZip将始终正确解码它们,请参见此处.
这是我想用libarchive实现的,即我想将它传递给我的UTF-8编码pathname并将其存储在zip文件中而不进行任何转换.
我添加了"set locale"方法作为(不满意的)答案.
这是一种解决方法,它将使用系统的区域设置来存储路径名,即生成的 zip 文件可以在同一系统上正确解码,但不可移植。
这并不令人满意,我发布这个只是为了表明这不是我想要的。
将全局区域设置设置为""如下所述:
std::locale::global(std::locale(""));
Run Code Online (Sandbox Code Playgroud)
然后读回来:
std::locale loc;
std::cout << loc.name() << std::endl;
// output: English_United States.1252
// may of course be different depending on system settings
Run Code Online (Sandbox Code Playgroud)
然后pathname使用 进行设置archive_entry_update_pathname_utf8。
zip 文件现在包含使用 Windows-1252 编码的文件名,因此我的 Windows 可以读取它们,但它们在 Linux 等上显示为垃圾。
未来
UTF-8 文件名存在libarchive 问题。整个故事相当复杂,但听起来他们可能会在 libarchive 4.0 中添加更好的 UTF-8 支持。
| 归档时间: |
|
| 查看次数: |
1106 次 |
| 最近记录: |