2010-04-08 291 views
11

我想知道如果我們有任何類可以壓縮文件夾或文件。我使用qprocess壓縮,它得到了壓縮,但我無法使用普通的壓縮工具解壓縮它。任何人都可以讓我知道如何使用qt api類壓縮文件夾/文件使用qt壓縮文件夾/文件

回答

4

我不認爲你可以。據我所知qcompress和quncompress只提供壓縮流等。這意味着他們不會創建真正的zipfile所需的頭文件(也就是說哪些文件在文件中)。

然而,有一個開源的Qt庫叫做QuaZip,它使用zlib(附帶qt)並提供這一點。

25

幾年前,我有這樣一個問題,這裏是我的解決方案:

1)。得到QuaZip(這裏是link text

2)。包括quazip源項目文件

頁眉:

HEADERS += src/quazip/crypt.h \ 
      src/quazip/ioapi.h \ 
      src/quazip/quazip.h \ 
      src/quazip/quazipfile.h \ 
      src/quazip/quazipfileinfo.h \ 
      src/quazip/quazipnewinfo.h \ 
      src/quazip/unzip.h \ 
      src/quazip/zip.h \ 
      ... 

來源:

SOURCES += src/quazip/ioapi.c \ 
      src/quazip/quazip.cpp \ 
      src/quazip/quazipfile.cpp \ 
      src/quazip/quazipnewinfo.cpp \ 
      src/quazip/unzip.c \ 
      src/quazip/zip.c 
      ... 

3)。添加標題

#include "quazip/quazip.h" 
#include "quazip/quazipfile.h" 

4)。使用提取功能:

static bool extract(const QString & filePath, const QString & extDirPath, const QString & singleFileName = QString("")) { 

QuaZip zip(filePath); 

if (!zip.open(QuaZip::mdUnzip)) { 
    qWarning("testRead(): zip.open(): %d", zip.getZipError()); 
    return false; 
} 

zip.setFileNameCodec("IBM866"); 

qWarning("%d entries\n", zip.getEntriesCount()); 
qWarning("Global comment: %s\n", zip.getComment().toLocal8Bit().constData()); 

QuaZipFileInfo info; 

QuaZipFile file(&zip); 

QFile out; 
QString name; 
char c; 
for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) { 

    if (!zip.getCurrentFileInfo(&info)) { 
     qWarning("testRead(): getCurrentFileInfo(): %d\n", zip.getZipError()); 
     return false; 
    } 

    if (!singleFileName.isEmpty()) 
     if (!info.name.contains(singleFileName)) 
      continue; 

    if (!file.open(QIODevice::ReadOnly)) { 
     qWarning("testRead(): file.open(): %d", file.getZipError()); 
     return false; 
    } 

    name = QString("%1/%2").arg(extDirPath).arg(file.getActualFileName()); 

    if (file.getZipError() != UNZ_OK) { 
     qWarning("testRead(): file.getFileName(): %d", file.getZipError()); 
     return false; 
    } 

    //out.setFileName("out/" + name); 
    out.setFileName(name); 

    // this will fail if "name" contains subdirectories, but we don't mind that 
    out.open(QIODevice::WriteOnly); 
    // Slow like hell (on GNU/Linux at least), but it is not my fault. 
    // Not ZIP/UNZIP package's fault either. 
    // The slowest thing here is out.putChar(c). 
    while (file.getChar(&c)) out.putChar(c); 

    out.close(); 

    if (file.getZipError() != UNZ_OK) { 
     qWarning("testRead(): file.getFileName(): %d", file.getZipError()); 
     return false; 
    } 

    if (!file.atEnd()) { 
     qWarning("testRead(): read all but not EOF"); 
     return false; 
    } 

    file.close(); 

    if (file.getZipError() != UNZ_OK) { 
     qWarning("testRead(): file.close(): %d", file.getZipError()); 
     return false; 
    } 
} 

zip.close(); 

if (zip.getZipError() != UNZ_OK) { 
    qWarning("testRead(): zip.close(): %d", zip.getZipError()); 
    return false; 
} 

return true; 
} 

和歸檔功能:

static bool archive(const QString & filePath, const QDir & dir, const QString & comment = QString("")) { 

QuaZip zip(filePath); 
zip.setFileNameCodec("IBM866"); 

if (!zip.open(QuaZip::mdCreate)) { 
    myMessageOutput(true, QtDebugMsg, QString("testCreate(): zip.open(): %1").arg(zip.getZipError())); 
    return false; 
} 

if (!dir.exists()) { 
    myMessageOutput(true, QtDebugMsg, QString("dir.exists(%1)=FALSE").arg(dir.absolutePath())); 
    return false; 
} 

QFile inFile; 

// Получаем список файлов и папок рекурсивно 
QStringList sl; 
recurseAddDir(dir, sl); 

// Создаем массив состоящий из QFileInfo объектов 
QFileInfoList files; 
foreach (QString fn, sl) files << QFileInfo(fn); 

QuaZipFile outFile(&zip); 

char c; 
foreach(QFileInfo fileInfo, files) { 

    if (!fileInfo.isFile()) 
     continue; 

    // Если файл в поддиректории, то добавляем имя этой поддиректории к именам файлов 
    // например: fileInfo.filePath() = "D:\Work\Sources\SAGO\svn\sago\Release\tmp_DOCSWIN\Folder\123.opn" 
    // тогда после удаления части строки fileNameWithSubFolders будет равен "Folder\123.opn" и т.д. 
    QString fileNameWithRelativePath = fileInfo.filePath().remove(0, dir.absolutePath().length() + 1); 

    inFile.setFileName(fileInfo.filePath()); 

    if (!inFile.open(QIODevice::ReadOnly)) { 
     myMessageOutput(true, QtDebugMsg, QString("testCreate(): inFile.open(): %1").arg(inFile.errorString().toLocal8Bit().constData())); 
     return false; 
    } 

    if (!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileNameWithRelativePath, fileInfo.filePath()))) { 
     myMessageOutput(true, QtDebugMsg, QString("testCreate(): outFile.open(): %1").arg(outFile.getZipError())); 
     return false; 
    } 

    while (inFile.getChar(&c) && outFile.putChar(c)); 

    if (outFile.getZipError() != UNZ_OK) { 
     myMessageOutput(true, QtDebugMsg, QString("testCreate(): outFile.putChar(): %1").arg(outFile.getZipError())); 
     return false; 
    } 

    outFile.close(); 

    if (outFile.getZipError() != UNZ_OK) { 
     myMessageOutput(true, QtDebugMsg, QString("testCreate(): outFile.close(): %1").arg(outFile.getZipError())); 
     return false; 
    } 

    inFile.close(); 
} 

// + комментарий 
if (!comment.isEmpty()) 
    zip.setComment(comment); 

zip.close(); 

if (zip.getZipError() != 0) { 
    myMessageOutput(true, QtDebugMsg, QString("testCreate(): zip.close(): %1").arg(zip.getZipError())); 
    return false; 
} 

return true; 
} 

5)。享受;)

UPDATE:for CapDroid

/* Рекурсивно ищет все файлы в директории \a и добавляет в список \b */ 
static void recurseAddDir(QDir d, QStringList & list) { 

    QStringList qsl = d.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files); 

    foreach (QString file, qsl) { 

     QFileInfo finfo(QString("%1/%2").arg(d.path()).arg(file)); 

     if (finfo.isSymLink()) 
      return; 

     if (finfo.isDir()) { 

      QString dirname = finfo.fileName(); 
      QDir sd(finfo.filePath()); 

      recurseAddDir(sd, list); 

     } else 
      list << QDir::toNativeSeparators(finfo.filePath()); 
    } 
} 
+0

可以請你加** recurseAddDir(DIR,SL); **在回答這個方法.... – 2013-05-17 04:13:01

+0

@CapDroid完成! – mosg 2013-05-17 06:54:44

+0

@moseg thanks,brother ..讓我檢查 – 2013-05-17 12:37:11