最近研究chrome代码时,发现它的安装包使用7z,它的代码可以解压chrome.7z(Google提供的安装压缩包)。但是却无法解压我自己生成的“xxx.7z”。
相关的核心代码如下(截取部分)(lzma_util.cc):
if ((ret = SzExtract(&archiveStream.InStream, &db, i, &blockIndex,
&outBuffer, &outBufferSize, &offset, &outSizeProcessed,
&allocImp, &allocTempImp)) != SZ_OK) {
break;
}
std::wstring wfileName(location);
file_util::AppendToPath(&wfileName, UTF8ToWide(f->Name));
// If archive entry is directory create it and move on to the next entry.
if (f->IsDirectory) {
file_util::CreateDirectory(wfileName);
continue;
}
HANDLE hFile;
std::wstring directory = file_util::GetDirectoryFromPath(wfileName);
file_util::CreateDirectory(directory);
//SHCreateDirectoryEx(NULL, directory.c_str(), NULL);
hFile = CreateFile(wfileName.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
LOG(ERROR) << " ret = GetLastError()3; ";
ret = GetLastError();
break;
}
|
大概的逻辑是:
当file为目录时,创建目录。如果是文件,则首先提取文件所在的目录,并创建目录(如果不存在)。
但是经过查证发现,当使用自己的7z文件解压时,创建目录失败了。它创建目录的代码如下:
(file_util_win.cc)
bool CreateDirectory(const FilePath& full_path) {
if (DirectoryExists(full_path))
return true;
int err = SHCreateDirectoryEx(NULL, full_path.value().c_str(), NULL);
return err == ERROR_SUCCESS;
}
|
SHCreateDirectoryEx函数一个windows API。
最后发现SHCreateDirectoryEx只认得微软的"\\"路径分隔符,而不认识"/",所以在创建目录前将path中所有的"/"t替换成"\\"即可。
这里提供一个可用但不一定最佳的函数。
std::wstring& LzmaUtil::replace_all(std::wstring& str,const std::wstring& old_value,const std::wstring&new_value)
{
while(true) {
std::wstring::size_type pos(0);
if((pos=str.find(old_value))!=std::wstring::npos )
str.replace(pos,old_value.length(),new_value);
else break;
}
return str;
}
|
(replace_all(path,L"/",L"\\");)
阅读(2543) | 评论(0) | 转发(0) |