2010-04-08 9 views
11

je voudrais savoir si nous avons une classe en qt qui peut zip un dossier ou un fichier.je utilisé qprocess pour compresser, il a été compressé mais je suis incapable de le décompresser en utilisant un outil de zip normal .can quelqu'un peut me faire savoir comment pouvons-nous compresser un dossier/fichier en utilisant qt api classeszipping un dossier/fichier en utilisant qt

Répondre

4

Je ne pense pas que vous le pouvez. Pour autant que je sache, qcompress et quncompress ne fournissent que la compression des flux, etc. Cela signifie qu'ils ne créeront pas les en-têtes nécessaires pour un fichier zip réel (qui dit aussi quels fichiers sont dans le fichier).

Cependant, il existe une bibliothèque Qt open source appelée QuaZip qui utilise zlib (fournie avec qt) et fournit exactement cela.

25

Il y a quelques années, j'avais une question, et voici ma solution:

1). obtenir QuaZip (voici le link text)

2). inclure des sources quazip à votre fichier de projet

têtes:

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:

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). ajouter des en-têtes

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

4). utiliser la fonction de l'extrait:

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; 
} 

et la fonction archive:

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). en profiter;)

MISE À JOUR: pour 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

pouvez-vous s'il vous plaît ajouter ** recurseAddDir (dir, sl) **; cette méthode, en réponse .... –

+0

@CapDroid fait! – mosg

+0

@moseg merci, frère .. laissez-moi vérifier –

Questions connexes