Ce dont j'ai besoin est de pouvoir extraire les fichiers dans un fichier .rar dans des flux. Je crée un cas de test pour avoir un sentiment d'utilisation d'utiliser Source . Je cherche et je bricole pendant un moment, mais je ne peux pas comprendre comment utiliser la bibliothèque. Je suis surpris que je ne puisse même pas trouver de documentation ou un tutoriel pour cela, en considérant à quel point les archives communes sont communes.
J'ai fait un peu de progrès tout seul, mais cela ne fonctionne pas toujours. Certains fichiers sont extraits correctement. D'autres fichiers sont jumblés pour une raison quelconque (mais pas complètement em> les données binaires "ordures"). Tout ce que je sais jusqu'à présent, c'est généralement (mais pas toujours): p> ne fonctionne pas les fichiers de travail ont Les fichiers de travail ont Mais je ne sais pas pourquoi c'est. Ne peut toujours pas trouver de la documentation ou un exemple de travail. P> ci-dessous est la source de test de test que j'ai jusqu'à présent et un Exemple Archive RAR qui, lorsqu'il est extrait avec ce programme, a à la fois des fichiers fonctionnant et ne fonctionne pas. p> mise à jour: p> J'ai trouvé un fichier qui semble être (prétend être?) Le Documentation , mais selon le fichier, je ne fais rien de mal. Je pense que je pourrais être obligé de recourir à CRC en train de vérifier les tampons et de mettre en œuvre une solution de contournement s'il échoue. P> Source de solution (merci, Denis Krjuchkov!): P>
fileinfo.method = 48 code>. Ils semblent être des fichiers qui ont un ratio de compression de 100% - c'est-à-dire aucune compression p> li>
fileinfo.method = 49 code>,
50 code>,
51 code>,
52 code>, ou
53 code>, qui correspond à la vitesse de compression, le plus rapide, rapide, normal, bon, meilleur p> li>
ul>
/* put in the same directory as the unrar source files
* compiling with:
* make clean
* make lib
* g++ rartest.cpp -o rartest libunrar.so -lboost_filesystem
*/
#include <cstring>
#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>
#include <boost/crc.hpp>
#define _UNIX
#define RARDLL
#include "dll.hpp"
using namespace std;
namespace fs = boost::filesystem;
//char fileName[100] = "testout0.jpg\0";
//
//// doens't work
//int PASCAL ProcessDataProc(unsigned char* buffer, int buffLen) {
// cout << "writing..." << endl;
// ofstream outFile(fileName);
// cout << buffLen << endl;
// cout << outFile.write((const char*)buffer, buffLen) << endl;
// cout << "done writing..." << endl;
// fileName[7]++;
//}
int CALLBACK CallbackProc(unsigned int msg, long myBufferPtr, long rarBuffer, long bytesProcessed) {
switch(msg) {
case UCM_CHANGEVOLUME:
return -1;
break;
case UCM_PROCESSDATA:
memcpy(*(char**)myBufferPtr, (char*)rarBuffer, bytesProcessed);
*(char**)myBufferPtr += bytesProcessed;
return 1;
break;
case UCM_NEEDPASSWORD:
return -1;
break;
}
}
int main(int argc, char* argv[]) {
if (argc != 2)
return 0;
ifstream archiveStream(argv[1]);
if (!archiveStream.is_open())
cout << "fstream couldn't open file\n";
// declare and set parameters
RARHANDLE rarFile; // I renamed this macro in dll.hpp for my own purposes
RARHANDLE rarFile2;
RARHeaderDataEx fileInfo;
RAROpenArchiveDataEx archiveInfo;
memset(&archiveInfo, 0, sizeof(archiveInfo));
archiveInfo.CmtBuf = NULL;
//archiveInfo.OpenMode = RAR_OM_LIST;
archiveInfo.OpenMode = RAR_OM_EXTRACT;
archiveInfo.ArcName = argv[1];
// Open file
rarFile = RAROpenArchiveEx(&archiveInfo);
rarFile2 = RAROpenArchiveEx(&archiveInfo);
if (archiveInfo.OpenResult != 0) {
RARCloseArchive(rarFile);
cout << "unrar couldn't open" << endl;
exit(1);
}
fileInfo.CmtBuf = NULL;
// cout << archiveInfo.Flags << endl;
// loop through archive
int numFiles = 0;
int fileSize;
int RHCode;
int PFCode;
int crcVal;
bool workaroundUsed = false;
char currDir[2] = ".";
char tmpFile[11] = "buffer.tmp";
while(true) {
RHCode = RARReadHeaderEx(rarFile, &fileInfo);
if (RHCode != 0) break;
RARReadHeaderEx(rarFile2, &fileInfo);
numFiles++;
fs::path path(fileInfo.FileName);
fileSize = fileInfo.UnpSize;
crcVal = fileInfo.FileCRC;
cout << dec << fileInfo.Method << " " << fileInfo.FileName << " (" << fileInfo.UnpSize << ")" << endl;
cout << " " << hex << uppercase << crcVal << endl;
char fileBuffer[fileSize];
char* bufferPtr = fileBuffer;
// not sure what this does
//RARSetProcessDataProc(rarFile, ProcessDataProc);
// works for some files, but not for others
RARSetCallback(rarFile, CallbackProc, (long) &bufferPtr);
PFCode = RARProcessFile(rarFile, RAR_TEST, NULL, NULL);
// properly extracts to a directory... but I need a stream
// and I don't want to write to disk, read it, and delete from disk
// PFCode = RARProcessFile(rarFile, RAR_EXTRACT, currDir, fileInfo.FileName);
// just skips
//PFCode = RARProcessFile(rarFile, RAR_SKIP, NULL, NULL);
if (PFCode != 0) {
RARCloseArchive(rarFile);
cout << "error processing this file\n" << endl;
exit(1);
}
// crc check
boost::crc_32_type crc32result;
crc32result.process_bytes(&fileBuffer, fileSize);
cout << " " << hex << uppercase << crc32result.checksum() << endl;
// old workaround - crc check always succeeds now!
if (crcVal == crc32result.checksum()) {
RARProcessFile(rarFile2, RAR_SKIP, NULL, NULL);
}
else {
workaroundUsed = true;
RARProcessFile(rarFile2, RAR_EXTRACT, currDir, tmpFile);
ifstream inFile(tmpFile);
inFile.read(fileBuffer, fileSize);
}
ofstream outFile(path.filename().c_str());
outFile.write(fileBuffer, fileSize);
}
if (workaroundUsed) remove(tmpFile);
if (RHCode != ERAR_END_ARCHIVE)
cout << "error traversing through archive: " << RHCode << endl;
RARCloseArchive(rarFile);
cout << dec << "num files: " << numFiles << endl;
}
3 Réponses :
Vous semblez avoir posté du code source, mais pas de question réelle. P>
Avez-vous envisagé de regarder Page de rétroaction RARLABS (qui pointe vers leur forums p>
Aussi, voir: Cet article P>
Je ne peux pas obtenir (même un principal () code>) pour compiler. J'essaie de décompresser un fichier dans une archive RAR dans un tampon, à faire avec comme je le souhaite. J'ai parcouru vos liens. Rarlabs n'a pas de soutien à leur bibliothèque d'UNRARD que je connaisse - juste une bibliothèque d'irrécouvrable ouverte sans documentation.
Je ne trouve aucune DOCS en ligne non plus, mais il y a exemples em> vous pouvez utiliser: p>
aller à http://www.krugle.com , et dans le coin inférieur gauche de la page , entrez un mot clé comme cela devrait vous faire aller. p> rarropenarchiveex code>. Vous verrez des fichiers d'en-tête et de sources de divers projets open source qui utilisent une bibliothèque d'UNRAR. P>
Merci! Je vais jeter un coup d'oeil à travers certains d'entre eux. Espérons qu'au moins un de ces extraits directement à un tampon, et je peux comprendre comment faire la même chose.
Je ne suis pas familier d'unar, après une lecture rapide d'une documentation, je pense que vous supposez que CallBackProc est appelé exactement une fois par fichier. Cependant, je pense que cela peut l'appeler plusieurs fois. Il déballose certaines données alors appelle callbackProc code>, puis exploitent le morceau de données suivant et appelle à nouveau les appels
callbackProc code>, le processus est itéré jusqu'à ce que toutes les données soient traitées.
Vous devez vous rappeler combien d'octets sont réellement écrits sur la mémoire tampon et appendez de nouvelles données à compensation correspondante. P>
Il explique définitivement pourquoi les fichiers extraits échoués ont été jumelés mais pas toutes les ordures. Je relisons la documentation et cela ne m'a pas donné d'impression que cela pourrait exécuter le rappel plusieurs fois par fichier. Comment y penses-tu? Avoir un rappel exécuté périodiquement au milieu de l'extraction ne me semble pas très intuitive.
Je suppose que la raison est que les fichiers dans les archives peuvent être suffisamment importants et ne s'intégreraient pas à la mémoire disponible. Déballage de ces fichiers entièrement dans un tampon serait impossible ou au moins inefficace.
Peut-être qu'il y a un problème avec les caractères EOL (Archive faite sur Windows mais extraite sur UNIX), mais je ne suis pas si sûr ..
Je m'assonne à utiliser le bon
bufflen code> ou
FileSize code> lors de la lecture / de l'écriture sur les tampons. À ce stade, je suis prêt à simplement mettre le blâme sur la bibliothèque d'UNRAR.