.zip entpacken
-
hallo forum,
nach stundenlangem suchen hab ich mich halb tot gegoogelt und versuch es auf diesem wege.
problem:
server schickt client .zip file
client muss .zip file entpackenes sollte aus dem code heraus geschehen, also kein anderes programm, wie unzip oder so, aufrufen.
hat da einer plan? hat das schon mal jemand gemacht? wäre für jeden tip dankbar
hab was von "zlib" gelesen und auf deren homepage n beispielcode gelesen, jedoch scheint es sich dort um ein anderes (zlib) format zu handeln.
dort ist von einem tool namens "minizip"/"miniunzip" die rede, welche angeblich mit .zip formaten umgehen können. auch der sourcecode soll angeblich verfügbar sein, allerdings bin ich nicht fündig geworden, weder beim code, noch bei der dokugrüße aus berlin
davey
-
davey schrieb:
dort ist von einem tool namens "minizip"/"miniunzip" die rede, welche angeblich mit .zip formaten umgehen können. auch der sourcecode soll angeblich verfügbar sein, allerdings bin ich nicht fündig geworden, weder beim code, noch bei der doku
-
Hab mir das gerade heruntergeladen:
~ % find zlib-1.2.3 -name zip.h zlib-1.2.3/contrib/minizip/zip.h ~ % find zlib-1.2.3 -name unzip.h zlib-1.2.3/contrib/minizip/unzip.h
-
ohne Library geht es zur Not etwa in der Art:
/* Annahme: filenamep enthält (char *) ptr Namen des gzip-ten files */ char hstr[1024]; FILE *infile; unsigned char bbuf[1024*10]; int cnt; sprintf(hstr,"gzip -d <%s",filenamep); /* Annahme: gzip ist über $PATH erreichbar */ infile = popen(hstr,"r"); if (infile != NULL) { /* jetzt kann von infile byte/blockweise eingelesen werden, etwa: */ while (1) { cnt = fread(bbuf,(size_t) sizeof(bbuf[0]),(size_t) sizeof(bbuf),infile); if (cnt < 0) { /* Fehlerbehandlung */ .... break; } else { /* Umkopieren bbuf[0..(cnt-1)] */ if (cnt < (size_t) sizeof(bbuf)) /* Ende Einlesen? */ break; } ... } ... pclose(infile); }
Ist kein ausgetesteter Code, sondern nur als Anregung zu verstehen.
popen() arbeiter analog system(), man kann nur den Output direkt einlesen. Hab ich so ähnlich schon gemacht, ist simpel und geht wunderbar. Dauert natürlich etwas länger als über einen Library-Call, ob das tragbar ist, hängt natürlich von der Anwendung ab.
-
Wozu denn, wenn die Library das ohnehin kann?
-
hi,
ohne library ist schon interessant, allerdings rufst du ja "gzip" auf, genau das wollt ich ja nicht,
hab mir die files von oben genannter url gesaugt und bin am rumprobieren,
vielen dank für den hinweis nman!
allerdings versteh ich noch immer net so recht mit dem zip format, vor einigen tagen dacht ich noch es gäbe einen ZIP standard, den verschiedene hersteller supporten???
nun scheint mir, dass der name zip völlig chaotisch gebraucht wird für ".zip", "gzip" und dieses ominöse zlib-format, was ja auch angeblich irgnd n zip is*verwirrt*
ma sehen, was ich mit den files so reißen kann, momentan frag ich mich was eine ".a" datei ist...
diese libz.a wird nämlich im Makefile erwartet...
bei diesem gesaugten zlib-projekt compilt man einfach zwei ebenen höher und sie is da, aber wie kriege ich die in mein projekt? oder sind das zwingend benötigte files, die ich auch in mein projekt inbinden muss?gruß davey
-
ok,
libz.a is ne library, die in /usr/include liegt
was ist der unterschied zwischen libXYZ.so und libXYZ.a
in meinem eclipse mit CDT plugin kann ich anscheinend mit der -l option eine z-lib integrieren, allerdings werden noch immer funktionen nicht gefunden
na ma guggen
gruß davey
-
zlib ist schon die richtige Antwort. Schau einfach in den Source von minizip. Da hast Du ein Beispiel.
Ich habe für meinen Tntnet (www.tntnet.org) einen C++-Wrapper geschrieben. Wenn Du Tntnet installierst, findest Du in der libtntnet eine Klasse tnt::unzipFile. Am einfachsten ist die Verwendung von tnt::unzipFileStream. Schau einfach in den Header tnt/unzipfile.h. Hier ein kleines Beispiel:
#include <tnt/unzipfile.h> #include <iostream> int main() { try { tnt::unzipFile f("datei.zip"); // öffne ZIP-Datei tnt::unzipFileStream d(f, "datei.txt"); // öffne Datei innerhalb der ZIP-Datei std::cout << d.rdbuf() << std::endl; // gebe Datei auf std::cout aus return 0; } catch (const std::exception& e) { // bei Fehlern wird eine Exception ausgelöst std::cerr << e.what() << std::endl; return -1; } }
-
davey schrieb:
ok,
libz.a is ne library, die in /usr/include liegt
was ist der unterschied zwischen libXYZ.so und libXYZ.a
in meinem eclipse mit CDT plugin kann ich anscheinend mit der -l option eine z-lib integrieren, allerdings werden noch immer funktionen nicht gefunden
na ma guggen
gruß davey
Deine libz.a liegt bestimmt nicht unter /usr/include (oder Du hast ein ziemlich verhunztes System). Unter /usr/include liegen die Header-Dateien, welche die Schnittstelle zur Library beschreiben. Die libz.a liegt unter /usr/lib.
Die libz.a ist eine statische Bibliothek. Die libz.so die dynamische. Linke ich ein statisches Programm, werden alle Funktionen in mein Programm kopiert. Das ergibt ziemlich grosse Binaries. Dafür wird die libz.a benötigt. Normalerweise linke ich dynamisch. Dann wird nur ein Verweis auf die Funktionen in libz.so eingebaut. Die Binaries werden weitaus kleiner, benötigen aber zur Laufzeit die libz.so.
Tommi
-
danke für den tip, ich werds mir ma anschauen!
allerdings denke ich, dass es momentan nur am linken liegt, denn in /usr/include/ liegt einerseits eine libz.so und eine libz.a
wenn ich nun in meinem eclipse bei der -l option des linkers "z" mitgebe, dann wird wohl die libz.so statt der libz.a integriert
also muss ich nur noch wissen, wie man ne .a datei verlinkt...
gruß davey
-
hey Tommi,
da warste schneller, vielen dank für diese ausführliche erklärung, da gehen einem lichter auf...
(natürlich meinte ich /usr/lib/ hab ich ja vor n paar tagen hier gelernt
nur weiß ich noch immer nich wie ich das in meinem eclipse hinbekomme, im minizipprojekt hab ich im makefile auf meine /usr/lib/libz.a verwiesen und es ging,.
kann ja net so schwer sein das im eclipse hinzubekommen, allerdings werden dort die makefiles automatisch erzeugt, sodass man da leider nich einfach was reinschreiben kann
mfg davey
-
davey schrieb:
wenn ich nun in meinem eclipse bei der -l option des linkers "z" mitgebe, dann wird wohl die libz.so statt der libz.a integriert
Warum willst Du denn die statische Version verwenden? Nimm die dynamische.
also muss ich nur noch wissen, wie man ne .a datei verlinkt...
Kommt auf Deinen Linker an, beim ld zB mit der Option -static.
-
hi,
also um es präzise zu formulieren möchte ich den code von miniunzip (später mal bis aufs nötigste abgespeckt) in mein c++projekt einbinden.
im makefile von miniunzip wird die statische zlib.a beim kompilieren respektive linken(?) hinzugefügt, (deshalb wollt ich die statische)
nun gut das konnte ich bei den kompileroptionen mit angeben, allerdings bin ich nicht befähigt die "main" umzuschreiben und so in mein projekt einzubinden, dass alle referenzen stimmenals workaround rufe ich nun doch das programm mit "system("./miniunzip XYZ.zip")" auf, was ich ja eigentlich nicht wollte
gruß davey
-
Du musst doch nur die Funktionen aus dem Header verwenden und zur libz.so linken, was davon schaffst Du nicht?
-
hi nman,
das miniunzip ist ein eigenständiges c-programm, im make file steht folgendes:
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a .c.o: $(CC) -c $(CFLAGS) $*.c all: miniunz miniunz: $(UNZ_OBJS) $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
die haben da noch ne eigene libz.a, daher wollte ich krampfhaft die statische lib haben...
ich wollte nun lediglich die main umbenennen, um sie aus meinem c++programm aufrufen zu können und das bekomme ich einfach nicht hin,
in "miniunz.c" ist die main, die hab ich ma zipnow() genannt, weiterhin hab ich die files ioapi.c/.h und die unzip.c/.h in meinem projekt... die miniunz.c includiere ich in meiner main (ob das funzt...?), nun wird zwar die funktion zipnow() ohne probleme gefunden, jedoch ruft diese funktion zb die funktion "unzOpen(zipfilename)" aus unzip.c/.h aufgerufen, und da zieh ich beim linken immer folgende error meldung:./main.o: In function `zipnow(int, char*)':../miniunz.c:543: undefined reference to `unzOpen' :../miniunz.c:551: undefined reference to `unzOpen'
eigentlich wollte ich ja sowas in der art machen, was tntnet-tommi vorgeschlagen hat, aber durch seinen code steig ich erstma so gar nicht durch, mit den tnt-namespaces... da hab ich hart keinen plan, habs zwar ma kurzzeitig versucht, wollte aber dann doch lieber den anderen weg verfolgen
gruß davey
-
Hi,
wenn Dir das ohne Namespaces lieber ist und die Fehlerbehandlung habe ich auch weg gelassen. Einfacher geht es dann nicht mehr:
#include <tnt/unzipfile.h> #include <iostream> using namespace std; using namespace tnt; int main() { unzipFile f("datei.zip"); // öffne ZIP-Datei unzipFileStream d(f, "datei.txt"); // öffne Datei innerhalb der ZIP-Datei cout << d.rdbuf() << endl; // gebe Datei auf cout aus }
Tommi
-
davey schrieb:
das miniunzip ist ein eigenständiges c-programm, im make file steht folgendes
Und es gibt eine zip.h bzw. unzip.h, die verwendest Du.
-
hi,
@nman
ja, das is ja das komische, die unzip.h wird in der miniunzip.c includiert, wodurch ja die funktionen nach meinem verständnis bereitstehen sollten...@tnt-tommi:
ich werde es jetzt nochmal probieren!
werde mir deine unzipfile.h anguggen, in mein projekt integrieren, wenn du meinst dass das so easy is, kann das ja net so schwer sein, oder ich bin einfach zu dumm*niemals aufgib*
stelle es mir so vor,dass ich deine unzpfile.h und deren referenzierte files in mein projekt integriere und dann nach deinem code aufrufen, ma gugen was passiert
eigentlich meinte ich auch die namespaces in deiner unzipfile.hgruß davey
p.s. danke für euren support
-
davey schrieb:
ja, das is ja das komische, die unzip.h wird in der miniunzip.c includiert, wodurch ja die funktionen nach meinem verständnis bereitstehen sollten...
Ja, in der miniunzip.c. Die kannst Du aber nicht includen, die zeigt Dir nur, wie Du die Funktionen aus unzip.h verwenden sollst.