Lecture de données compressées

Publié le Publié dans Lecture de données
Description

Les jeux de données présents sur le Mésocentre peuvent être compressés pour réduire l’espace disque requis pour leur stockage. Deux types de compression sans-perte sont utilisés principalement :

Utilisation

Pour lire les jeux de données compressés à l’aide de l’une ou l’autre de ces librairies, il existe plusieurs possibilités :

 Lecture de fichier compressés par la Zlib (.gz)
  • Décompresser le fichier vers un répertoire temporaire avant le lancement du programme de lecture et lire ce fichier temporaire :
    gunzip -c fichier.gz > /tmp/fichier.tmp
    lecture.exe
    rm /tmp/fichier.tmp
  • Décompresser le fichier vers un répertoire temporaire depuis le programme de lecture :
    • En C:
      system(gunzip -c fichier.gz > /tmp/fichier.tmp);

      system(rm /tmp/fichier.tmp);
    • En Fortran:
      call system(gunzip -c fichier.gz > /tmp/fichier.tmp)

      call system(rm /tmp/fichier.tmp)
  • Utiliser la Zlib pour la lecture sans décompression préalable (méthode optimale) :Le principe de zlib est relativement simple. Votre programme utilise des instructions read et write : il suffit de les remplacer par les instructions de la zlib. En d’autres termes, plutôt que d’utiliser les instructions fournies par la glibc pour lire et écrire dans un fichier, on utilise les fonctions de la zlib. Voici un exemple de lecture dans un fichier :Un extrait de programme avant modification :
            int fh;
            char buffer[BUFFER_MAX_SIZE];
            fh = open(filename, O_RDONLY);
            while(read(fh, buffer, BUFFER_MAX_SIZE))
                  traitement_du_buffer(buffer);
            close(fh);
    

    Le même extrait de programme après modification :

            #include <zlib.h>
            gzFile gzfh = NULL;
            char buffer[BUFFER_MAX_SIZE];
            gzfh = gzopen(filename, "rb");
            while(gzread(gzfh, buffer, BUFFER_MAX_SIZE))
                  traitement_du_buffer(buffer);
            gzclose(gzfh);

    Et qu’est-ce qui a changé ? Le type du descripteur du fichier qui était int et qui devient gzFile, et les instructions d’entrées/sorties qui forcément appartiennent à la zlib. Plus le mode de lecture du fichier qui est spécifié à l’ouverture du fichier. Par contre, tous les autres arguments n’ont pas changé.

    Pour la compilation, il suffit d’ajouter l’option -lz  à la commande de compilation : gcc main.c -lz -o monprog

 Lecture de fichier compressés par la libbzip2 (.bz2)
  • Décompresser le fichier vers un répertoire temporaire avant le lancement du programme de lecture et lire ce fichier temporaire :
    bunzip2 -c fichier.gz > /tmp/fichier.tmp
    lecture.exe
    rm /tmp/fichier.tmp
  • Décompresser le fichier vers un répertoire temporaire depuis le programme de lecture :
    • En C :
      system(bunzip2 -c fichier.gz > /tmp/fichier.tmp);

      system(rm /tmp/fichier.tmp);
    • En Fortran :
      call system(bunzip2 -c fichier.gz > /tmp/fichier.tmp)

      call system(rm /tmp/fichier.tmp)
    • En IDL :
      openr, lunit, filename, /GET_LUN, /COMPRESS
  • Utiliser la libbzip2 pour la lecture sans décompression préalable (méthode optimale) :Le principe de libbzip2 est relativement simple. Votre programme utilise des instructions read et write : il suffit de les remplacer par les instructions de la libbzip2. En d’autres termes, plutôt que d’utiliser les instructions fournies par la glibc pour lire et écrire dans un fichier, on utilise les fonctions de la zlib. Voici un exemple de lecture dans un fichier :
           #include <bzlib.h>
           FILE*   f;
            BZFILE* b;
            int     nBuf;
            char    buf[ /* whatever size you like */ ];
            int     bzerror;
            int     nWritten;
     
            f = fopen ( "myfile.bz2", "r" );
            if ( !f ) {
              /* handle error */
            }
            b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 );
            if ( bzerror != BZ_OK ) {
              BZ2_bzReadClose ( &bzerror, b );
              /* handle error */
            }
     
            bzerror = BZ_OK;
            while ( bzerror == BZ_OK && /* arbitrary other conditions */) {
              nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ );
              if ( bzerror == BZ_OK ) {
                /* do something with buf[0 .. nBuf-1] */
              }
            }
            if ( bzerror != BZ_STREAM_END ) {
               BZ2_bzReadClose ( &bzerror, b );
               /* handle error */
            } else {
               BZ2_bzReadClose ( &bzerror );
            }

    Pour la compilation, il suffit d’ajouter l’option -lbz2  à la commande de compilation : gcc main.c -lbz2 -o monprog