Après plusieurs jours de recherche, je désespère complètement de ne pas trouver de lib simple pour zipper / unzipper un fichier en C++ sous Windows avec msvc, avec licence libre (LGPL de préférence).
J'ai besoin d'aller modifier des fichiers dans une archive (changer des valeurs dans un xlsx en fait).
J'ai tenté plusieurs trucs :
7z : Le SDK LZMA n'a aucune doc, aucune explication sur la compilation. Si on prend les sources de 7zip et le dll installé sur la machine, il manque quand même une doc pour nous dire quels objets utiliser. Très mal foutu.
libarchive : J'ai réussi à compiler pour visual, fait marcher le truc mais j'ai des erreurs de deflate. La librairie ne doit pas le gérer.
Libzippp : J'ai réussi à compiler pour visual, mais le link ne semble pas marcher avec ce compilo.
Minizip : J'ai eu du mal à comprendre, il faut aussi zlib, j'ai du mal à comprendre les instructions pour faire le lien entre les deux
QuaZIP : Je n'ai pas trop eu le temps de creuser encore, mais il faut lier ça avec zlib. Il faut l'installer ou faire ça avec les sources ?
Bref, j'imagine qu'être sur Windows n'aide pas trop et qu'à force d'avoir le nez dedans j'ai un peu de mal mais si vous pouviez m'éclairer un peu sur ce sujet.
Et pourquoi pas? Le produit sur lequel je bosse impose un SGBD, on s'est débrouillé pour que le client ait le choix entre plusieurs SGBD, mais il doit en choisir un parmi la liste qu'on lui propose, ou bien faire un très gros chèque pour qu'on lui développe l'interface avec le SGBD de ses rêves...
L'installation d'un truc comme 7z n'est pas une grosse contrainte, c'est nettement moins lourd, qu'un runtime SQLServer, Oracle ou autre...
@Deedolith, pourquoi ouvrir un shell additionnel? Depuis quand, doit on ouvrir un shell pour exécuter un processus externe en lui passant une ligne de commande? Je suis certainement capable de gérer de la compression, mais 7z le fait probablement bien mieux que moi, donc question. Est ce que je me fais chier à faire ma propre compression, ou est ce que je fais appel à 7z? Ma réponse à moi, c'est que j'ai autre chose à faire que de m’occuper de compression, donc 7z se charge de ce détail, c'est parfait
fs::path extractArchive(fs::path const & archive)
{
/// L'assert: archive est un fichier valide et connu comme une archive (zip,arj,7z ...)
assert(fs::exists(archive) && isArchive(archive));
/// on va chercher le chemin de 7z
auto settings = appIniFile();
auto unpacker = fs::path{settings->value("import/unpacker").toString().toStdWString()};
if (!fs::exists(unpacker)){
throw std::runtime_error{"7z.exe not found!"};
}
/// le répertoire de décompactage
auto tempDir = locateApplicationPath(QApplication::applicationDisplayName().toStdWString()) / L"temp";
fs::create_directories(tempDir);
/// On fait un sous-répertoire spécialement pour l'archive à traiter...
tempDir /= getFileName(archive);
/// On prépare la ligne de commande
auto args = QStringList{} << "x" << "-aoa" << dbpfString(archive) <<
QString{"-o%1"}.arg(dbpfString(tempDir));
/// C'est parti...
QProcess process{};
process.start(dbpfString(unpacker),args);
if (process.waitForFinished(-1)){
return tempDir;
}
throw std::runtime_error{QString{"extract process finished whith status %1 "}.arg(process.exitCode()).toStdString()};
}
dbpfString est une fonction qui transforme un fs::path, std::string, std::wstring en QString. Là j'utilise Qt parce que le reste du programme utilise Qt, mais le code ne sera pas franchement différent avec un CreateProcess de l'API Win32. fs::path est un alias, qui en fonction du compilateur, est std::path ou boost::filesystem::path.
Bref, j'imagine qu'être sur Windows n'aide pas trop
Qu'est ce que ça veut dire cette remarque ?
Zipper/dezipper avec la zlib, ça se fait bien. Je l'ai fait ... sous Windows justement... (mais avec un code portable), mais c'est du code que j'ai fait pour ma boîte, donc je ne peux pas le faire ici.
zlib permet de décompresser des blocs zippés, voir de décompresser le format Gzip, qui est assez simple : un petit header de quelques octets et ensuite un bloc zippé.
Après, si vraiment tu veux faire un fichier zip, il y a une gestion de l'arborescence avec. Mais en soit, c'est pas bien méchant à faire :
Comme tu vois, des petits blocs avec le nom de fichier, des tailles, et ensuite des blocs "zippés" pour chaque fichier. (ce que fait minizip mais qui peut se faire à la main si tu veux)
Tout dépend ce que tu veux faire. Si tu veux absolument faire des fichiers ZIP (que ton client pourra ouvrir avec winzip), voit avec gzip (zlib) si tu n'as qu'un seul fichier a mettre, ou alors minizip si tu veux en mettre plusieurs.
Si ton seul but est de faire un fichier compact sur le disque que seul ton programme peut relire, fait toi un gzip, ou même directement un bloc zippé (deflate) avec zlib.
Ok merci de la piste. En fait dans mon cas comme j'avais précisé, c'est pour modifier des valeurs dans un xlsx.
Il vaut peut-être mieux utiliser une librairie pour manipuler excel, plutôt que renommer le fichier en zip et manipuler de façon hasardeuse les XML ? Il peut y avoir plein de dépendances la dedans.
Je suis à 100% d'accord avec @Deedolith, aussi bien pour le manque quasi-total de contrôle lors de l'exécution dans un processus externe, que de l'utilisation de librairies dédiées à ce type de tâche.
Pour le .xlsx, sauf erreur de ma part, il est tout à fait possible d'avoir une source de données externe au fichier, un fichier CSV, via "file" ou "http", REST etc..., et autres formats "conventionnels" de transfert de données.
Il est donc assez simple de modifier ces sources de données plutôt que le fichier .xlsx lui-même.
Si le fait d'avoir les données "fourrées" dans le fichier .xlsx est un "pré-requis", genre tradition de la dinde de Thanksgiving, il existe tout un SDK .NET pour manipuler des fichiers au format OOXML, c'est du .NET donc utilisable en C++/CLI :
Non c'est absolument un xlsx qui possède des images et compagnie.
@Deedolith
C'était la piste initiale mais c'était au niveau des licences que ça coinçait. Procédures de la boite. Mais pour info en allant toucher les valeurs dans les xml ça marche.
J'avais réussi à avoir un résultat avec QuaZip. Mais finalement ça va se faire via QaxObject pour éviter d'ajouter des dépendances, contraintes de la boite. Merci à tous !
C'était la piste initiale mais c'était au niveau des licences que ça coinçait. Procédures de la boite. Mais pour info en allant toucher les valeurs dans les xml ça marche.
Oui, dans des cas particulier, ou dans le monde des bisounours, ça marche. Par expérience, on finis toujours par rencontrer, tôt ou tard, le cas qui merdoie.
Ma méthode permet de s'éviter de se palucher les 500 pages de norme pour des nefles, 7z.exe fait le boulot, la belle affaire, j'appelle 7z pour faire le boulot. C'est exactement la même chose que Sql Server ou Oracle ou n'importe quel SGBD fait le boulot, je ne vais pas me palucher mon propre SGBD alors que j'en ai plein sur le marché qui font le boulot bien mieux que je ne pourrais jamais le faire... Et ça s'applique à tout ou presque, pour la crypto, j'ai des libs de crypto qui vont bien, je veux de la 3d, c'est pas le choix qui manque... Quelque part je suis un grand enfant qui joue au légo, mon boulot en tant que développeur professionnel, c'est souvent de mixer tout ça pour en faire un truc utilisable par le commun des mortels.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html