在libarchive中设置UTF-8路径名头

时间:2014-12-03 09:31:28

标签: c++ utf-8 zip 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中设置路径名标题有四个函数:

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中正确显示文件名。

我确信我的输入字符串编码正确,因为我将它们转换为Qt QString实例,这些实例在我的代码的其他部分中运行得非常好:

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

我还尝试按this example

的建议更改libarchive的选项
archive_write_set_options(a, "hdrcharset=UTF-8");

但是这次调用失败了,所以我认为我必须设置一些其他选项,但我的想法已经用完......

更新2

我已经做了一些关于zip格式的阅读。它允许以UTF-8编写文件名,这样OS X / Linux / Windows 8/7-Zip / WinZip将始终正确解码它们,例如, here

这是我想要使用libarchive实现的,即我想将它传递给我的UTF-8编码pathname,并将其存储在zip文件中而不进行任何转换。

我已将“设置区域设置”方法添加为(不满意的)答案。

2 个答案:

答案 0 :(得分:2)

这是一种使用系统的区域设置存储路径名的解决方法,即生成的zip文件可以在同一系统上正确解码,但不可移植。

这不令人满意,我只是张贴这个来表明它不是我想要的。

将全局区域设置设置为"" explained here

std::locale::global(std::locale(""));

然后再读回来:

std::locale loc;
std::cout << loc.name() << std::endl;
// output: English_United States.1252
// may of course be different depending on system settings

然后使用pathname设置archive_entry_update_pathname_utf8

zip文件现在包含用Windows-1252编码的文件名,因此我的Windows可以读取它们,但它们在例如垃圾邮件中显示为垃圾邮件。 Linux操作系统。

<强>未来

UTF-8文件名有libarchive issue个。整个故事非常复杂,但听起来他们可能会在libarchive 4.0中添加更好的UTF-8支持。

答案 1 :(得分:0)

我使用libarchive-3.3.3在ZIP存档中使用了UTF-8文件名,并使用了这种精确的流程(顺序很重要!):

entry = archive_entry_new();
archive_entry_set_pathname_utf8(entry, utf8Filename);
archive_entry_set_pathname(entry, utf8Filename);

在切换archive_entry_set_pathname_utf8 / archive_entry_set_pathname时,条目在Windows资源管理器的ZIP功能中显示为乱码。这对我来说适合德国变音符号(但应该对每个UTF-8字符都适用)。甚至适用于2字节和3字节UTF-8字符(NFC / NFD)。

//加法 该过程必须在LANG变量设置为支持UTF-8的语言环境的环境中运行(在我的情况下为“ LANG = de_DE.UTF-8”)。没有这种环境,该过程将无法生成正确的UTF-8字符。