Skip to content

Commit 837a5de

Browse files
committedSep 9, 2019
Significant improvement in support for solid compressed archives
- Dozens of times faster - All contents are decoded with a single call to ExtractAll()
1 parent e122fcd commit 837a5de

File tree

2 files changed

+124
-32
lines changed

2 files changed

+124
-32
lines changed
 

‎fileloader/fileloader7zarchive.cpp

+123-31
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct Qt7zFileInfo
4848
bool isEncrypted;
4949
};
5050

51+
/** Used by lib7zip to read binary streams.
52+
* Usually 7z archive itself.
53+
*/
5154
class Qt7zStreamReader : public C7ZipInStream
5255
{
5356
private:
@@ -130,23 +133,20 @@ class Qt7zStreamReader : public C7ZipInStream
130133
}
131134
};
132135

133-
/** Used by lib7zip to write binary streams.
134-
* Specifically, it is used when expanding from 7z content files.
135-
*/
136-
class Qt7zStreamWriter : public C7ZipOutStream
136+
class Qt7zBaseStreamWriter : public C7ZipOutStream
137137
{
138-
private:
138+
protected:
139139
QIODevice *m_outStream;
140-
QString m_strFileName;
141140
int m_nFileSize;
141+
int m_index;
142142
public:
143-
Qt7zStreamWriter(QIODevice *outStream, QString fileName) :
144-
m_outStream(outStream),
145-
m_strFileName(fileName)
143+
Qt7zBaseStreamWriter() :
144+
m_outStream(nullptr),
145+
m_index(-1)
146146
{
147147
}
148148

149-
virtual ~Qt7zStreamWriter()
149+
virtual ~Qt7zBaseStreamWriter()
150150
{
151151
}
152152

@@ -204,8 +204,78 @@ class Qt7zStreamWriter : public C7ZipOutStream
204204
wprintf(L"SetFileSize:%ld\n", size);
205205
return 0;
206206
}
207+
virtual int ReopenForIndex(unsigned int index)
208+
{
209+
wprintf(L"SetIndex:%ld\n", index);
210+
m_index = index;
211+
return 0;
212+
}
213+
};
214+
215+
/** Used by lib7zip to write binary streams.
216+
* Output binary stream expanded from 7z archive to QIODevice.
217+
*/
218+
class Qt7zStreamWriter : public Qt7zBaseStreamWriter
219+
{
220+
private:
221+
QString m_strFileName;
222+
public:
223+
Qt7zStreamWriter(QIODevice *outStream, QString fileName)
224+
: Qt7zBaseStreamWriter()
225+
, m_strFileName(fileName)
226+
{
227+
m_outStream = outStream;
228+
}
229+
};
230+
231+
/** Used by lib7zip to write binary streams.
232+
* C7ZipArchive :: ExtractAll () is supported. Switch QIODevice when ReopenForIndex () is called
233+
*/
234+
class Qt7zMultiStreamWriter : public QObject, public Qt7zBaseStreamWriter
235+
{
236+
Q_OBJECT
237+
238+
private:
239+
QList<Qt7zFileInfo>* m_fileInfoList;
240+
QString m_baseDirPath;
241+
void finalize()
242+
{
243+
if(m_outStream) {
244+
m_outStream->close();
245+
delete m_outStream;
246+
m_outStream = nullptr;
247+
m_nFileSize = 0;
248+
}
249+
}
250+
251+
public:
252+
Qt7zMultiStreamWriter(QString basePath, QList<Qt7zFileInfo>* pFileInfoList, QObject* parent)
253+
: QObject(parent)
254+
, Qt7zBaseStreamWriter()
255+
, m_baseDirPath(basePath)
256+
, m_fileInfoList(pFileInfoList)
257+
{
258+
}
259+
~Qt7zMultiStreamWriter()
260+
{
261+
finalize();
262+
}
263+
virtual int ReopenForIndex(unsigned int index)
264+
{
265+
wprintf(L"SetIndex:%ld\n", index);
266+
m_index = index;
267+
finalize();
268+
Qt7zFileInfo info = m_fileInfoList->value(index);
269+
if(!info.isDir) {
270+
const QString abso = QDir(m_baseDirPath).filePath(QString::number(index));
271+
m_outStream = new QFile(abso);
272+
m_outStream->open(QIODevice::WriteOnly);
273+
}
274+
return 0;
275+
}
207276
};
208277

278+
209279
static Qt7zFileInfo fromC7ZipArchiveItem(C7ZipArchiveItem& item, QString packagePath, size_t pre_total) {
210280
Qt7zFileInfo prop;
211281
std::wstring strVal;
@@ -255,8 +325,10 @@ static Qt7zFileInfo fromC7ZipArchiveItem(C7ZipArchiveItem& item, QString package
255325
* Unzip the 7z archive using lib7zip.
256326
* In the case of a solid, it is expanded in the temp directory and then re-read if necessary.
257327
*/
258-
class FileLoader7zArchivePrivate
328+
class FileLoader7zArchivePrivate : public QObject
259329
{
330+
Q_OBJECT
331+
260332
public:
261333
QString m_packagePath;
262334
C7ZipArchive* m_pArchive;
@@ -270,8 +342,9 @@ class FileLoader7zArchivePrivate
270342
QTemporaryDir* m_tempDir;
271343
bool m_hasExtractedFiles;
272344

273-
FileLoader7zArchivePrivate(QString sevenzippath, QString extensionOfFile)
274-
: m_packagePath(sevenzippath)
345+
FileLoader7zArchivePrivate(QString sevenzippath, QString extensionOfFile, QObject* parent)
346+
: QObject(parent)
347+
, m_packagePath(sevenzippath)
275348
, m_pArchive(nullptr)
276349
, stream(sevenzippath.toStdString(), extensionOfFile.toStdWString())
277350
, m_tempDir(nullptr)
@@ -405,6 +478,36 @@ class FileLoader7zArchivePrivate
405478

406479
return true;
407480
}
481+
// bool extractToDir(const QString &dirpath)
482+
// {
483+
// m_tempDir = new QTemporaryDir(dirpath);
484+
// m_tempDir->setAutoRemove(true);
485+
// qDebug() << "tempdir:" << m_tempDir->path();
486+
487+
// unsigned int numItems = 0;
488+
// m_pArchive->GetItemCount(&numItems);
489+
490+
// wprintf(L"%d\n", numItems);
491+
// size_t pre_total = 0;
492+
493+
// for(uint32_t i = 0;i < numItems;i++) {
494+
// Qt7zFileInfo info = m_fileInfoList[i];
495+
// if(info.isDir)
496+
// continue;
497+
// const QString abso = QDir(m_tempDir->path()).filePath(QString::number(i));
498+
// QFile file(abso);
499+
// if(file.open(QIODevice::WriteOnly)) {
500+
// Qt7zStreamWriter oStream(&file, info.fileName);
501+
// m_pArchive->Extract(i, &oStream);
502+
// file.close();
503+
// } else {
504+
// qDebug() << "Qt7zPackagePrivate::extractToDir()" << "file:" << abso << "can't open";
505+
// return false;
506+
// }
507+
// }//for
508+
// m_hasExtractedFiles = true;
509+
// return true;
510+
// }
408511
bool extractToDir(const QString &dirpath)
409512
{
410513
m_tempDir = new QTemporaryDir(dirpath);
@@ -416,26 +519,12 @@ class FileLoader7zArchivePrivate
416519

417520
wprintf(L"%d\n", numItems);
418521
size_t pre_total = 0;
522+
Qt7zMultiStreamWriter multiWriter(m_tempDir->path(), &m_fileInfoList, this);
523+
m_pArchive->ExtractAll(&multiWriter);
419524

420-
for(uint32_t i = 0;i < numItems;i++) {
421-
Qt7zFileInfo info = m_fileInfoList[i];
422-
if(info.isDir)
423-
continue;
424-
const QString abso = QDir(m_tempDir->path()).filePath(QString::number(i));
425-
QFile file(abso);
426-
if(file.open(QIODevice::WriteOnly)) {
427-
Qt7zStreamWriter oStream(&file, info.fileName);
428-
m_pArchive->Extract(i, &oStream);
429-
file.close();
430-
} else {
431-
qDebug() << "Qt7zPackagePrivate::extractToDir()" << "file:" << abso << "can't open";
432-
return false;
433-
}
434-
}//for
435525
m_hasExtractedFiles = true;
436526
return true;
437-
}
438-
};
527+
}};
439528

440529
bool FileLoader7zArchive::initializeLib()
441530
{
@@ -462,7 +551,7 @@ void FileLoader7zArchive::uninitializeLib()
462551

463552
FileLoader7zArchive::FileLoader7zArchive(QObject* parent, QString sevenzippath, QString extensionOfFile, bool extractSolidArchiveToTemporaryDir)
464553
: IFileLoader(parent)
465-
, d(new FileLoader7zArchivePrivate(sevenzippath, extensionOfFile))
554+
, d(new FileLoader7zArchivePrivate(sevenzippath, extensionOfFile, this))
466555
, m_volumepath(sevenzippath)
467556
, m_valid(d->m_pArchive != nullptr)
468557
, m_extractSolidArchiveToTemporaryDir(extractSolidArchiveToTemporaryDir)
@@ -533,3 +622,6 @@ FileLoader7zArchive::~FileLoader7zArchive()
533622
d=nullptr;
534623
}
535624
}
625+
626+
627+
#include "fileloader7zarchive.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.