Russian Qt Forum
Сентябрь 30, 2024, 00:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QZipReader или как распаковать zip  (Прочитано 22695 раз)
0xFF
Гость
« : Март 01, 2011, 15:08 »

Доброго времени суток
Проблема в следующем: нужно распаковать файл MS Office (.docx)
Версия Qt 4.7.0
Из стандартного для этого нашел QZipReader, но что-то он вообще не хотит работать:
Код
C++ (Qt)
QZipReader zip_reader(QLatin1String("doc.docx"));
if (zip_reader.exists()) {
   zip_reader.extractAll("extr");
   zip_reader.close();
}
Пробывал писать вместо extr путь к папке.
Такой код показывает файлы в архиве:
Код
C++ (Qt)
foreach (QZipReader::FileInfo info, zip_reader.fileInfoList()) {
   qDebug() <<  info.filePath;
}
видимо они все же должны как-то извлекаться, раз он их видит. Пробывал с обычными архивами - та же песня, файлы показывает, но ничего не извлекает =(

Что я делаю не так? Может кто-нибудь выложит рабочий проектик где этот QZipReader будет работать, он ведь не документирован, информация кусочна, может я что-либо не так подключил.
« Последнее редактирование: Март 01, 2011, 15:10 от 0xFF » Записан
victor_yacovlev
Гость
« Ответ #1 : Март 01, 2011, 19:53 »

Попробуйте QaZip (http://quazip.sourceforge.net/). Документация вполне полная, работоспособность проверена.
Записан
0xFF
Гость
« Ответ #2 : Март 01, 2011, 23:17 »

Спасибо
Библиотеку эту собрал, вроде работает, но вопрос остался открытым, все же хотел бы разузнать нерабочесть данного класса в моих руках)
Записан
voral
Гость
« Ответ #3 : Март 02, 2011, 01:47 »

Странно. Только сегодня фокал под свои нужды это дело все работает (с docx не побовал) вот прямо рабочий код
Код:
#include <qvzip.h>
int main(int argc, char *argv[])
{
        if  (argc<2) return 1;
        QVZipReader zip(argv[1]); // имя файла архива
        zip.extractAll(argv[2]); // куда извлекать
        zip.close();
        return 0;
}

qvzip.h - это Qtшный qzip.cpp
QVZipReader - это Qtшный QZipReader

в данном случае я только переименовал. Это все работает. Хотя одно но я qzip.cpp qzipwriter.h qzipreader.h взял из сырцов qutim (просто под руку попались) - но, думаю, они там Qt-шные.

Кстати, там (в этих файлах) все понятно, так что навставляете туда qDebug`ов или дебагером пройдитесь.

ЗЫ Не знаю кто там пермишены открутил (может qutim-овцы постарались, а может Qt шники не доделали). Но там это недолго поправить. У меня теперь линуксовые права храняться и восстанавливаются.

ЗЗЫ В винде тоже работало

Если поможет - присылайте какой либо файл в формате docx - попробую...
« Последнее редактирование: Март 02, 2011, 01:49 от voral » Записан
0xFF
Гость
« Ответ #4 : Март 02, 2011, 10:57 »

Подключил попавшиеся вам под руку файлы из qutim. Результат оказался тот же, я поковырялся в qzip.cpp, вообщем незнаю правильно это или нет, но все файлы в архиве определяются как Symlink.
Я закомментил в функции extractAll следующее:
Код
C++ (Qt)
foreach (FileInfo fi, allFiles) {
const QString absPath = destinationDir + QDir::separator() + fi.filePath;
//if (fi.isFile) {
QFile f(absPath);
if (!f.open(QIODevice::WriteOnly))
return false;
f.write(fileData(fi.filePath));
f.setPermissions(fi.permissions);
f.close();
//}
}
и о чудо, файлы разархивировались, но опять трабл, разархивируются только файлы в корне архива, т.е. архивированные папки идут лесом. Такое ощущение что проблемы в ОС (Win7), еще попилю код, надеюсь все же вытащу папки)
« Последнее редактирование: Март 02, 2011, 11:02 от 0xFF » Записан
voral
Гость
« Ответ #5 : Март 02, 2011, 13:36 »

Подключил попавшиеся вам под руку файлы из qutim. Результат оказался тот же, я поковырялся в qzip.cpp, вообщем незнаю правильно это или нет, но все файлы в архиве определяются как Symlink.
и о чудо, файлы разархивировались, но опять трабл, разархивируются только файлы в корне архива, т.е. архивированные папки идут лесом. Такое ощущение что проблемы в ОС (Win7), еще попилю код, надеюсь все же вытащу папки)
Видимо я наврал (память подвела). Под линем не разархивируется сходу. И "обычный" zip архив тоже. Возможно есть отличия по формату со стандартным zip. (http://en.wikipedia.org/wiki/ZIP_%28file_format%29) можно сравнить с кодом.
Возможно docx так же имеет дополнительные поля которые не умеет этот класс обрабатывать. (судя по "внешнему виду" кода он писался на коленке и "лишь бы работало то что нужно в конкретной задаче").
Кстати, в qzip.cpp есть следующее:
Код:
#if defined(Q_OS_WIN)
....
#  define S_ISDIR(x) ((x) & 0040000) > 0
#  define S_ISREG(x) ((x) & 0170000) == S_IFREG
#  define S_IFLNK 020000
#  define S_ISLNK(x) ((x) & S_IFLNK) > 0
...
Может эта байда "пееопределяет" значения для стандартного зипа?
Записан
crackedmind
Гость
« Ответ #6 : Март 02, 2011, 14:03 »

Похоже все проблемы вот в этой функции
Код
C++ (Qt)
void QZipPrivate::fillFileInfo(int index, QVZipReader::FileInfo &fileInfo) const
{
   FileHeader header = fileHeaders.at(index);
   fileInfo.filePath = QString::fromLocal8Bit(header.file_name);
   const quint32 mode = (qFromLittleEndian<quint32>(&header.h.external_file_attributes[0]) >> 16) & 0xFFFF;
   fileInfo.isDir = S_ISDIR(mode);
   fileInfo.isFile = S_ISREG(mode);
   fileInfo.isSymLink = S_ISLNK(mode);
   fileInfo.permissions = modeToPermissions(mode);
   fileInfo.crc32 = readUInt(header.h.crc_32);
   fileInfo.size = readUInt(header.h.uncompressed_size);
   fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
}
 
Т.к. не срабатывает правильно проверка на fi.isFile

Цитировать
Может эта байда "пееопределяет" значения для стандартного зипа?
Эта вся беда вообще из линуксов =)
Записан
voral
Гость
« Ответ #7 : Март 02, 2011, 14:27 »

Цитировать
Может эта байда "пееопределяет" значения для стандартного зипа?
Эта вся беда вообще из линуксов =)
Хм. Пи компиляции под виндой у меня именно на этот код идут варнинги "переопределено"
Цитировать
In file included from ..\src\main.cpp:6:

..\src\/qvzip.h:59:1: warning: "S_ISDIR" redefined

In file included from ..\..\..\Qt\2010.05\qt\mkspecs\win32-g++/qplatformdefs.h:61,
правда не на все
Записан
0xFF
Гость
« Ответ #8 : Март 02, 2011, 14:57 »

Не глядя глубоко, это дело чинится парсингом строки с файлом из архива, строка содержит название директорий, где должен лежать файл, по этим названиям восстанавливаем иерархию и распихиваем файлы, пока обойдусь QuaZIP, но думаю вернусь к доделке этого распихивания)
Записан
NortT
Гость
« Ответ #9 : Июнь 26, 2011, 07:40 »

Ну что? У получилось у тебя что-нибудь? Я сейчас столкнулся как раз с этой же проблемой Улыбающийся Дай знать, если получилось. Вообще сейчас  у меня в проекте используется OSDABZip, но там нет такой фичи, как QByteArray QZipReader::fileData(const QString &fileName) const, по крайней мере я не нашел.
Записан
ритт
Гость
« Ответ #10 : Июнь 26, 2011, 10:18 »

дело в том, что QZipReader понимает только пермижены в схеме Unix, тогда как в данном .docx используется схема пермиженов FAT (а ещё все даты 01.01.1980)
могу добавить поддержку схемы FAT/VFAT/NTFS/HPFS в QZipReader 4.8, если создадите таску на http://bugreports.qt.nokia.com/

з.ы. quazip - отстой
Записан
NortT
Гость
« Ответ #11 : Июнь 26, 2011, 11:35 »

2Константин: я пытаюсь распаковать обычный зип, зипованый линуксовым зипом.
Записан
ритт
Гость
« Ответ #12 : Июнь 26, 2011, 11:41 »

у меня работает отлично. правда, я внёс ряд изменений в свою версию...
давайте компилябельный пример с тестовым архивом.
Записан
NortT
Гость
« Ответ #13 : Июнь 26, 2011, 12:27 »

Вот. Список файлов в архиве выводит в дебаг, файлы из архива не вытаскиваются.
Код:
$ dpkg -s zip | grep -i version
Version: 3.0-3ppa2
« Последнее редактирование: Июнь 26, 2011, 12:29 от NortT » Записан
ритт
Гость
« Ответ #14 : Июнь 26, 2011, 15:12 »

сначала у меня ругалось на экстра-блоки и я было решил, что дело в них, но оказалось, что я просто сломал у себя парсер экстра-блоков...потом ещё вспомнил, что QZipReader  экстра-блоки вообще игнорирует - т.е. дело точно не в них.

заменил в примере
qDebug()<<list.at(i).filePath;
на
qDebug()<<list.at(i).filePath << list.at(i).isDir << list.at(i).isFile << list.at(i).isSymLink << list.at(i).size;
и сразу стало ясно - читайте http://www.prog.org.ru/index.php?topic=16992.msg125304#msg125304
« Последнее редактирование: Июнь 26, 2011, 16:21 от Константин » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.117 секунд. Запросов: 21.