Lire un fichier dans un zip

JoJoSJoJoS Membre
13:43 modifié dans API AppKit #1
Bonjour à  tous !!

J'ai fouillé un peu sur le site mais rien trouvé pour mon problème.

Alors voilà  :
Mon but est de récupérer sur internet un fichier zip et de lire le contenu d'un fichier présent à  l'intérieur.
Pour corser les choses, je ne veux pas enregistrer de fichier sur le disque dur, donc tout doit se faire en mémoire.

J'ai déjà  réussi à  faire ça en java, mais la je ne trouve rien pour ouvrir une archive en Cocoa, ni même en C d'ailleurs...

Si quelqu'un à  son idée, voir même solution sur le problème !! Ca serait super génial !!

Merci !!

Réponses

  • JoJoSJoJoS Membre
    septembre 2007 modifié #2
    Bon, je viens de voir dans la doc de NSURLDownload sa méthode delegate download:shouldDecodeSourceDataOfMIMEType: qui, apparement, décode 3 types de fichiers :
    • MacBinary ("application/macbinary")
    • Binhex ("application/mac-binhex40")
    • gzip ("application/gzip")

    En revanche, je ne sais pas si mon fichier sera décodé si il est plutôt de type "application/zip"...
    Je teste ça ce soir !

    Par contre, mon fichier sera obligatoirement enregistrer sur le disque...
    Bref, ca règle pas vraiment mon problème, mais ça me laisse une porte de sortie si je n'arrive pas à  faire ce que je souhaitais au départ.
  • AliGatorAliGator Membre, Modérateur
    13:43 modifié #3
    Ce que tu cherches à  faire est a mon avis assez bas niveau dans le sens où ce n'est pas de la manipluation de fichier à  zipper/dézipper mais de la décompression de données à  la volée (en mémoire).
    Quand je dis "assez bas niveau" je veux dire "y'a sans doute rien de si spécifique dans les API de Cocoa" et je pense donc du coup que tu devrais te tourner du côté des API C.

    Je pense bien sûr en particulier à  "libzip", librairie qui est fournie/installée avec OSX donc que tu dois avoir en standard, et qui devrait te fournir tout ce dont tu as besoin ; j'ai pas regardé la page man de libzip ceci dit mais bon à  mon avis c'est de ce côté qu'il faut creuser.

    Pourquoi ne veux-tu pas enregistrer le fichier sur le disque (quitte à  l'enregistrer en fichier temporaire qui pourra se détruire après dès que tu n'en n'as plus besoin) ? les répertoires genre /tmp et les commandes genre tmpfile sont faite pour ça, non ? Et ce serait plus simple à  mon avis (car tu as plus d'outils pour manipuler des fichiers ZIP que des données ZIp en mémoire), mais bon.
  • JoJoSJoJoS Membre
    13:43 modifié #4
    Ouais, je me disais bine qu'il fallait passer par du C.
    Je voulais que ce soit en mémoire pour faire une application transportable facilement. Quelle puisse être exécutée à  partir d'une clé usb par exemple.

    Mais ce n'est pas bien grave, je vais d'abord essayer de le faire en passant par un fichier sur le dur, puis je verrais bien si je m'en sors avec la libzip. En tout cas, à  première vue, elle à  l'air de bien correspondre à  ce que je recherche !

    Merci AliGator !!!
  • schlumschlum Membre
    13:43 modifié #5
    Pourquoi un fichier sur le dur ??

    Y a plein de moyen de récupérer le contenu d'une URL en mémoire... Ex, pour NSURLConnection :

    + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
    


    Ca va récupérer le contenu de la requête dans un objet NSData
  • JoJoSJoJoS Membre
    13:43 modifié #6
    Oui, j'ai bien compris l'intérêt de NSURLConnection, mais je veux récupérer un fichier zip, donc j'aurai un NSData de données compressées...

    C'est pour cela que je postais : comment décompresser une archive zip en mémoire ?

    NSURLDownload me permettrait apparemment de télécharger l'archive, puis de la décompresser mais sur le dur.

    C'est bête quand même...

    Sinon, hier j'ai essayé d'utiliser NSURLDownload dans un projet Fundation, mais je n'arrive pas à  télécharger.
    En fait, ça arrive trop vite au return.
    Je suppose donc que NSURLDownload télécharge dans un processus à  part et de ce faite, mon appli n'attend pas que celui ci soit fini.

    J'ai donc fait une boucle while en testant la fin du téléchargement, mais ça reste bloqué (boucle infinie à  jamais !).
    Bref, ce soir je test mais dans une application graphique, je pense que ça fonctionnera mieux.
  • schlumschlum Membre
    13:43 modifié #7
    Es-tu sûr que NSURLDownload puisse "dézipper" ? Car "zip" (pkzip) et "gzip", c'est pas exactement la même chose...
  • JoJoSJoJoS Membre
    13:43 modifié #8
    Bin pour l'instant je ne suis sur de rien... J'ai pas réussi à  télécharger avec NSURLDownload..
    Je referai le test ce soir si j'ai le temps.

    Mais je me dis qu'avec un peut de chance, c'est la méthode qu'utilise Safari pour extraire automatiquement les fichiers zip après leur téléchargement.
    Je verrai bien et je vous tiendrai informé !

    Mais gzip ne permet pas de décompresser des fichiers zip ? Parce que du coup je suis plus pessimiste...
    Bref, je verrai bien ca quand j'aurai fait tourner mon appli de test.
  • schlumschlum Membre
    13:43 modifié #9
    "gzip" sur une archive créée par le Finder :

    schlum$ gzip -d Desktop/Archive.zip<br />gzip: Desktop/Archive.zip: unknown suffix -- ignored
    
  • AliGatorAliGator Membre, Modérateur
    septembre 2007 modifié #10
    Ce n'est pas avec cette méthode que Safari dézippe les fichiers ZIP. Ca n'a vraiment rien à  voir du tout.
    Tu devrais en effet prendre en considération la remarque de schlum...

    (Pour les définitions et différences entre "archivage" et "compression", voir la fin du post)

    - gzip est le nom d'un système de compression de données (ça utilise l'algo "deflate" en fait, qui est un combiné de LZW et d'un codage Huffman). Ca prend un flux binaire en entrée, et ça le compresse en sortie.
    C'est donc un algo qui agit sur un flux de données (par exemple du texte, le code source d'une page HTML par exemple, puisque c'est un algo pultôt adapté à  ce genre de cas). Ou alors qui agit sur un fichier unique (en appliquant l'algo sur le contenu dudit fichier, tout bêtement).
    --> Tu ne peux pas archiver plusieurs fichiers dans un seul fichier ".gz" (format gzip), puisque c'est un format de compression d'un flux unique de données : ça ne gère pas l'aspect archivage, c'est à  dire le groupement de plusieurs fichiers en un seul avec une sorte de catalogue/liste des noms originaux des fichiers et leur position dans le fichier archive etc.
    (C'est pour ça qu'on voit parfois circuler des fichiers ".tar.gz", qui n'est autre qu'un fichier ".tar" qui a été gzippé, le format TAR étant, lui, un format d'archivage (sans compression) permettant donc de grouper plusieurs fichiers en un avant d'appliquer le gzippage)

    - ZIP est un format d'archivage et de compression : il compresse chaque fichier à  mettre dans l'archive à  l'aide de l'algo "deflate" (LZW+Huffman, le même que celui utilisé par gzip), et ensuite il archive les données gzippées dans un fichier unique, le munissant d'un header par fichier (indiquant comment a été compressé le fichier, sa checksum, etc) ainsi que d'un "central directory", sorte de table des matières listant les fichiers dans l'archive.

    La grande différence entre les 2 formats est donc que ZIP est une archive (groupement de plusieurs fichiers en un seul) en plus de compresser (via l'algo "deflate" en général, bien qu'en fait il supporte d'autres algos comme BWT ou autre) les données qu'elle archive. gzip n'est que le nom d'une compression de données (algo deflate), sans gestion de l'aspect "archivage".

    ---

    Si les classes NSURLDownload & co savent gérer le gzip (donc la décompression de données compressées par l'algo deflate), c'est typiquement pour pouvoir décoder un flux binaire reçu par le réseau (par HTTP par exemple), car certains serveurs web envoient par exemple le code source (de leurs pages HTML) compressé avec l'algo deflate/gzip. C'est bien là  le cas d'un flux de données unique. Et pas d'un fichier et encore moins d'une archive ZIP archivant plusieurs fichiers
    --> La gestion du format ZIP est donc bien plus vaste que la simple gestion de l'algo deflate (et donc de la compression gzip) puisqu'elle inclut la gestion du format d'archive ZIP, qui utilise gzip mais contient bien plus de choses aussi.

    Safari utilise l'utilitaire de OSX "BOMArchiveHelper" (qui, lui, utilise la librairie libzip ou les outils utilitaires zip/unzip j'imagine) pour décompresser les archives qu'il a téléchargées. Il utilise ce logiciel sur les fichiers une fois ces derniers téléchargés, et ne les décompresse pas à  la volée en mémoire, évidemment, lui...

    Côté bibliothèques, zlib c'est pour gérer le format gzip (deflate), libzip c'est pour gérer des fichiers au format ZIP (originellement PKZIP)

    Définitions
    Archive : groupement de plusieurs fichiers en un seul (avec indexation des divers fichiers archivés, avec leur nom, pour pouvoir effectuer un désarchivage et donc retrouver les fichiers d'origine, ça va de soi). les images disques peuvent être considérées comme un format d'archivage à  la limite. Le format tar est un bon exemple de format ne faisant que de l'archivage de plusieurs fichiers en un seul, sans pour autant compresser ces données.
    Compression : réduction (dans la mesure du possible) de la taille d'un flux de données ou d'un fichier, en utilisant des algos statistiques par exemple (probabilité de répétition de données, etc). Il existe de la compression avec perte (on enlève des données jugées peu importantes, quitte à  perdre en qualité) comme celle qu'on trouve dans le JPEG ou le MP3 par exemple, et la compression sans perte, que l'on trouve dans les formats de compression de fichier, telles que les compressions LZW, deflate, BWT (utilisé par bzip2)... permettant une fois le fichier décompresser de retrouver l'original intact.
  • Philippe49Philippe49 Membre
    13:43 modifié #11
    Sympa ces précisions  8--)
  • JoJoSJoJoS Membre
    13:43 modifié #12
    Merci pour ces explications !!

    J'avais déjà  compris cette différence entre compression et archive en faisant mes recherches, mais je ne savais pas à  quoi servait gzip.

    Ca ne sera pas aussi magique que ce que j'espérai...  :-\\

    Il va donc falloir que je télécharge le zip, que je lance dans un processus la décompression de celui ci, puis que je supprime le zip.
    Et éventuellement, que je charge en mémoire le fichier décompressé puis que je le supprime.

    Je vais essayer de faire ça ce soir !!
  • schlumschlum Membre
    13:43 modifié #13
    Je ne pense pas que charger le fichier zip sur le disque soit nécessaire... À voir comment fonctionne libzip.
  • JoJoSJoJoS Membre
    13:43 modifié #14
    Bon, j'ai réussi à  faire marcher ma classe de Download, mais comme prévu, elle ne desarchive pas le fichier zip.
    Il va donc me falloir essayer d'utiliser la libzip mais je n'ai pour l'instant rien trouvé dessus pour mac os x...

    Bref, je vais fouiller un peu !
  • schlumschlum Membre
    13:43 modifié #15
    dans 1189149636:

    Bon, j'ai réussi à  faire marcher ma classe de Download, mais comme prévu, elle ne desarchive pas le fichier zip.
    Il va donc me falloir essayer d'utiliser la libzip mais je n'ai pour l'instant rien trouvé dessus pour mac os x...

    Bref, je vais fouiller un peu !


    Euh... Tu sais, c'est une bibliothèque universelle ; elle tourne sur tous les OS, donc pas la peine de chercher quelque-chose spécifique à  Mac OS X ; c'est du C et ça fonctionne partout pareil  :P
  • AliGatorAliGator Membre, Modérateur
    13:43 modifié #16
    Bon après une autre solution que d'utiliser libzip serait d'appeler l'utilitaire "zip" (ou "unzip") en ligne de commande via un NSTask, mais bon, franchement, ça fait plus propre d'utiliser libzip et ce sera un bon exercice pour apprendre à  utiliser une lib externe :)
  • JoJoSJoJoS Membre
    13:43 modifié #17
    J'avais déjà  essayer à  l'époque de lancer via un NSTask la commande unzip. Mais je ne sais plus trop pourquoi, j'y arrivais pas...
    Je vais retenter pour voir.

    Pour la libzip, je testerai après avoir réussi à  extraire puis lire mon fichier.
    Et puis c'est sur, c'est un bon exercice que je ferai !!!

    En tout cas, merci à  vous 2 !! 

    Je vous tiens au courant !!!
  • schlumschlum Membre
    13:43 modifié #18
    Et quand t'auras bien compris comment fonctionne libzip, tu pourras faire un Framework Obj-C dessus et le proposer ici  :p :p
  • JoJoSJoJoS Membre
    13:43 modifié #19
    Ouais !! C'est une superbe idée ça !!!

    Ca m'apprendra à  faire un framework !
    Merci !!

    Mais il faut pas être trop pressé, pour l'instant je me bats pour faire fonctionner unzip en NSTask...
  • Bonjour,


     


    Comment faire apres telechargement du fichier zip pour le dezipper avec une barre de progress????


     


    Merci


Connectez-vous ou Inscrivez-vous pour répondre.