• Super User

    [Tutorial] Funzioni GZ con PHP

    Ecco qui una bella supposta per le GZ 😄

    Ciao Raga, scrivo queste righe sperando che possano servire in futuro... Qui
    spiegherò come utilizzare la compressione di files e le relative funzioni che
    potranno essere utili... Esse riguardano soprattutto il filesistem, in quanto
    le funzioni per comprimere possono essere tante. Allora Cominciamo...
    PERCHE' COMPRIMERE??
    Perchè così risparmiamo spazio... :stordita:

    SI POSSONO CREARE ARCHIVI??
    Ho fatto in modo di creare degli pseudo-archivi serializzando i dati. Quindi
    essi non saranno visibili nei programmi per la gestione degli archivi.

    QUANDO SI COMINCIA??
    Ora... 😄 😄 😄
    Allora... Inizialmente analizziamo le funzioni principali per comprimere i
    singoli files. Avevo creato una piccola classe, ed ora la analizzeremo insieme.

    
    <?php
    class gz_single &#123;
    
        /* Inizializza le variabili */
        var $source;
        var $dest;
        var $level;
        var $pointer;
        var $gzdata;
        var $data;
        var $status;
    
        function compress&#40;$source, $dest, $level&#41;
        &#123;
            /* Inizializza le variabili */
            $this->source = $source;
            $this->dest = $dest;
            $this->level = $level;
    
            /* Controlla che il file d'origine esista e che sia leggibile */
            if&#40;!is_file&#40;$this->source&#41; OR !file_exists&#40;$this->source&#41; OR !is_readable&#40;$this->source&#41;&#41; exit&#40;"Error 1: Source file doesn't exists or it's not readable!
    "&#41;;
    
            /* Controlla che il file di destinazione non sia di sola lettura */
            if&#40;is_file&#40;$this->dest&#41; AND !is_writeable&#40;$this->dest&#41;&#41; exit&#40;"Error 2&#58; The destination file it's not writeable"&#41;;
    
            /* Arrotonda il livello di compressione */
            $this->level = round&#40;$this->level&#41;;
    
            /* Controlla il livello e se è troppo grande, lo porta al massimo */
            if&#40;$this->level == 'MAX' OR $this->level > 9&#41; $this->level = 9;
    
            /* Controlla il livello e se è troppo piccolo, lo porta al minimo */
            if&#40;$this->level == 'MIN' OR $this->level < 1&#41; $this->level = 1;
    
            /* Prende i dati dal file d'origine */
            $this->data = file_get_contents&#40;$this->source&#41;;
    
            /* Comprime i dati del file d'origine */
            $this->gzdata = gzcompress&#40;$this->data, $this->level&#41;;
    
            /* Scrive i dati compressi nel file di destinazione */
            $this->status = file_put_contents&#40;$this->dest, $this->gzdata&#41;;
    
            /* Ritorna i valori positivi e negativi in base all'esito dell'operazione */
            if&#40;$this->status&#41; return TRUE; else return FALSE;
        &#125;
    
        function decompress&#40;$source, $dest&#41;
        &#123;
            /* Inizializza le variabili */
            $this->source = $source;
            $this->dest = $dest;
    
            /* Controlla che il file d'origine esista e che sia leggibile */
            if&#40;!is_file&#40;$this->source&#41; OR !file_exists&#40;$this->source&#41; OR !is_readable&#40;$this->source&#41;&#41; exit&#40;"Error 1&#58; Source file doesn't exists or it's not readable!
    "&#41;;
    
            /* Controlla che il file di destinazione non sia di sola lettura */
            if&#40;is_file&#40;$this->dest&#41; AND !is_writeable&#40;$this->dest&#41;&#41; exit&#40;"Error 2&#58; The destination file it's not writeable"&#41;;
    
            /* Prende i dati dal file d'origine */
            $this->gzdata = file_get_contents&#40;$this->source&#41;;
    
            /* Comprime i dati del file d'origine */
            $this->data = gzuncompress&#40;$this->gzdata&#41;;
    
            /* Scrive i dati decompressi nel file di destinazione */
            $this->status = file_put_contents&#40;$this->dest, $this->data&#41;;
    
            /* Ritorna i valori positivi e negativi in base all'esito dell'operazione */
            if&#40;$this->status&#41; return TRUE; else return FALSE;
        &#125;
    &#125;
    ?>
    
    

    Come vedete, ho creato solo due funzioni per questa classe, quelle fondamentali.
    Analizziamo intanto la prima funzione, quella che comprime, poi passeremo
    all'altra, che servirà a decomprimere il contenuto del file.

    
    /* Controlla che il file d'origine esista e che sia leggibile */
    if&#40;!is_readable&#40;$this->source&#41;&#41; exit&#40;"Error 1&#58; Source file doesn't exists or it's not readable!
    "&#41;;
    
    /* Controlla che il file di destinazione non sia di sola lettura */
    if&#40;is_file&#40;$this->dest&#41;&#41; AND !is_writeable&#40;$this->dest&#41;&#41; exit&#40;"Error 2&#58; The destination file isn't writeable"&#41;;
    
    

    Sono due controlli, il primo verifica che il file sorgente sia leggibile, con
    la funzione [URL='http://it.php.net/is-readable']is_readable() e la seconda, che sia scrivibile, con la funzione
    [URL='http://it.php.net/is-writeable']is_writeable().
    In caso di errore, interrompono lo script e stampano un messaggio di errore.

    
    /* Arrotonda il livello di compressione */
    $this->level = round&#40;$this->level&#41;;
    
    /* Controlla il livello e se è troppo grande, lo porta al massimo */
    if&#40;$this->level == 'MAX' OR $this->level > 9&#41; $this->level = 9;
    
    /* Controlla il livello e se è troppo piccolo, lo porta al minimo */
    if&#40;$this->level == 'MIN' OR $this->level < 1&#41; $this->level = 1;
    
    

    Servono ad arrotondare il livello di compressione, ed a portarlo ad una cifra
    accettabile.
    [URL='http://it.php.net/round']round() serve ad arrotondare il numero.
    I due controlli, servono invece per ridurre o aumentare il numero se è troppo
    grande o troppo piccolo. Si possono utilizzare anche 'MIN' o 'MAX' per portarli
    al minimo od al massimo.

    
    /* Prende i dati dal file d'origine */
    $this->data = file_get_contents&#40;$this->source&#41;;
    
    

    [URL='http://it.php.net/file-get-contents']File_Get_Contents() serve a leggere un file ed a memorizzare
    il suo contenuto in una variabile, in questo caso $this->data.

    
    /* Comprime i dati del file d'origine */
    $this->gzdata = gzcompress&#40;$this->data, $this->level&#41;;
    
    

    Questa è la vera funzione che esercita la compressione: [URL='http://it.php.net/gzcompress']gzcompress()
    che comprime il file secondo il metodo COMPRESS. Gli argomenti sono: Il testo da
    comprimere ed il livello di compressione.

    
    /* Scrive i dati compressi nel file di destinazione */
    $this->status = file_put_contents&#40;$this->dest, $this->gzdata&#41;;
    
    /* Ritorna i valori positivi e negativi in base all'esito dell'operazione */
    if&#40;$this->status&#41; return TRUE; else return FALSE;
    
    

    [URL='http://it.php.net/file-put-contents']File_Put_Contents svolge invece il compito di scrivere nel file:
    Gli argomenti sono: Il percorso del file ed il contenuto da scrivere, in questo
    caso il contenuto compresso. Se il file non esiste, lo crea. Inoltre la funzione
    ritorna TRUE o FALSE in base all'esito della scrittura nel file di destinazione.

    Così abbiamo spiegato come si comprimo i files, opportunamente verificando la
    sintassi usata per gli argomenti. Ora spiegherò come decomprimare i file
    compressi con il metodo COMPRESS:

    
    /* Controlla che il file d'origine esista e che sia leggibile */
    if&#40;!is_readable&#40;$this->source&#41;&#41; exit&#40;"Error 1&#58; Source file doesn't exists or it's not readable!
    "&#41;;
    
    /* Controlla che il file di destinazione non sia di sola lettura */
    if&#40;is_file&#40;$this->dest&#41;&#41; AND !is_writeable&#40;$this->dest&#41;&#41; exit&#40;"Error 2&#58; The destination file it's not writeable"&#41;;
    
    

    Soliti controlli... Verifica che il file sorgente sia leggibile e che quello di
    destinazione non sia di sola lettura (se esiste).

    
    /* Prende i dati dal file d'origine */
    $this->gzdata = file_get_contents&#40;$this->source&#41;;
    
    

    Memorizza il contenuto del file in $this->gzdata

    
    /* Comprime i dati del file d'origine */
    $this->data = gzuncompress&#40;$this->gzdata&#41;;
    
    

    Decomprime il file con la funzione [URL='it.php.net/gzuncompress']gzuncompress(), che ha come unico argomento
    il testo da decomprimere.

    
    
    /* Scrive i dati decompressi nel file di destinazione */
    $this->status = file_put_contents&#40;$this->dest, $this->data&#41;;
    
    /* Ritorna i valori positivi e negativi in base all'esito dell'operazione */
    if&#40;$this->status&#41; return TRUE; else return FALSE;
    
    

    Scrive i dati 'puliti' nel file di destinazione, e memorizza in $this->status
    l'esito della scrittura.

    Così abbiamo descritto come funziona la compressione/decompressone dei
    files gz in formato COMPRESS.

    To be continued... :zizi:


  • Super User

    Questa ulteriore classe, descrive come gestire più files in un'unico archivio
    mediante serializzazione:

    
    <?php
    class gz_archive &#123;
    
        /* Inizializza le variabili */
        var $source;
        var $dest;
        var $level;
        var $pointer;
        var $gzdata;
        var $data;
        var $status = TRUE;
        var $key = 0;
        var $files = array&#40;&#41;;
        var $contents;
        var $count;
        var $fcontents;
        var $path;
    
        function gz_archive&#40;$path&#41;
        &#123;
            $this->path = $path;
        &#125;
    
        function compress&#40;$source, $level&#41;
        &#123;
            /* Inizializza le variabili */
            $this->source = $source;
            $this->level = $level;
            
            /* Controlla che $this->source sia un array */
            if&#40;!is_array&#40;$this->source&#41;&#41; exit&#40;"The source input must be an array"&#41;;
            
            /* Controlla che i files indicati nell'array esistano */
            foreach&#40;$this->source AS $key => $value&#41;
            &#123;
                if&#40;!is_file&#40;$this->source&#91;$key&#93;&#41;&#41; exit&#40;print_R&#40;$this->source&#91;$key&#93;&#41; . " isn't a file"&#41;;
            &#125;
    
            /* Arrotonda il livello di compressione */
            $this->level = round&#40;$this->level&#41;;
    
            /* Controlla il livello e se è troppo grande, lo porta al massimo */
            if&#40;$this->level == 'MAX' OR $this->level > 9&#41; $this->level = 9;
    
            /* Controlla il livello e se è troppo piccolo, lo porta al minimo */
            if&#40;$this->level == 'MIN' OR $this->level < 0&#41; $this->level = 0;
            
            /* Crea un array nel quale ci sarà il contenuto dei files */
            $this->count = count&#40;$this->source&#41;;
            
            while&#40;$this->data = file_get_contents&#40;$this->source&#91;$this->key&#93;&#41;&#41;
            &#123;
                print $this->data;
                $this->fcontents&#91;$this->source&#91;$this->key&#93;&#93; = $this->data;
                $this->key++;
                if&#40;$this->key >= $this->count&#41; break;
            &#125;
            
            /* Serializza l'array */
            $this->data = serialize&#40;$this->fcontents&#41;;
    
            /* Comprime i dati del file d'origine */
            $this->gzdata = gzcompress&#40;$this->data, $this->level&#41;;
    
            /* Scrive i dati compressi nel file di destinazione */
            $this->status = file_put_contents&#40;$this->path, $this->gzdata&#41;;
    
            /* Ritorna i valori positivi e negativi in base all'esito dell'operazione */
            if&#40;$this->status&#41; return TRUE; else return FALSE;
        &#125;
        
        function decompress&#40;&#41;
        &#123;
            /* Controlla se il file esiste o meno */
            if&#40;!is_file&#40;$this->path&#41;&#41; exit&#40;"File doesn't exists"&#41;;
            
            /* Riceve l'array */
            $this->data = file_get_contents&#40;$this->path&#41; or exit&#40;"Cannot read the file"&#41;;
    
            /* Lo decomprime */
            $this->data = gzuncompress&#40;$this->data&#41;;
            
            /* E restituisce l'array */
            $this->data = unserialize&#40;$this->data&#41;;
            
            /* Installa i files */
            foreach&#40;$this->data AS $filename => $contents&#41;
            &#123;
                print $contents;
                if&#40;!file_put_contents&#40;$filename, $contents&#41;&#41; $this->status = FALSE;
            &#125;
    
            /* Ritorna i valori positivi e negativi in base all'esito dell'operazione */
            if&#40;$this->status&#41; return TRUE; else return FALSE;
        &#125;
    &#125;
    ?>
    
    

    Il funzionamento è più o meno simile rispetto a quello della classe precedente, qui spiegherò
    le differenze... Trattiamo prima la compressione:

    
    /* Controlla che $this->source sia un array */
    if&#40;!is_array&#40;$this->source&#41;&#41; exit&#40;"The source input must be an array"&#41;;
    
    /* Controlla che i files indicati nell'array esistano */
    foreach&#40;$this->source AS $key => $value&#41;
    &#123;
        if&#40;!is_readable&#40;$this->source&#91;$key&#93;&#41;&#41; exit&#40;print_R&#40;$this->source&#91;$key&#93;&#41; . " isn't a file or is't readable"&#41;;
    &#125;
    
    

    due controlli: Il primo controlla che $this->source sia un'array,
    il secondo, che i percorsi indicati in esso siano leggibili.

    
    /* Crea un array nel quale ci sarà il contenuto dei files */
    $this->count = count&#40;$this->source&#41;;
    
    while&#40;$this->data = file_get_contents&#40;$this->source&#91;$this->key&#93;&#41;&#41;
    &#123;
        $this->fcontents&#91;$this->source&#91;$this->key&#93;&#93; = $this->data;
        $this->key++;
        if&#40;$this->key >= $this->count&#41; break;
    &#125;
    
    /* Serializza l'array */
    $this->data = serialize&#40;$this->fcontents&#41;;
    
    

    la sostanziale differenza stà proprio qua:
    [URL='http://it.php.net/count']Count() Conta gli elementi di un'array, in questo caso quello
    contenente i percorsi dei files da comprimere.

    Il while esegue l'operazione di recupero dei files dal percorso specificato, e
    li memorizza in $this->fcontents, forse vi sarà di più difficile comprensione,
    questo: $this->fcontents[$this->source[$this->key]] = $this->data; che memorizza
    in $this->fcontents['percorso_del_file'] il suo contenuto.

    Infine con [URL='http://it.php.net/serialize']serialize() Serializziamo l'array contenente
    i files ed il loro percorso.
    Poi crea l'archivio e vi mette dentro il contenuto compresso della serializzazione.

    Per quanto riguarda la decompressione dell'archivio, il codice è mutato qui:

    
    /* E restituisce l'array */
    $this->data = unserialize&#40;$this->data&#41;;
    
    /* Installa i files */
    foreach&#40;$this->data AS $filename => $contents&#41;
    &#123;
        print $contents;
        if&#40;!file_put_contents&#40;$filename, $contents&#41;&#41; $this->status = FALSE;
    &#125;
    
    

    In quanto, dopo che l'archivio è stato decompresso, bisogna deserializzarlo,
    con la funzione [URL='http://it.php.net/unserialize']unserialize(), che in questo caso restituirà l'array
    precedentemente creato.
    Il foreach, in questo caso, serve a 'installare' i files, nel percorso salvato
    durante la creazione dell'archivio, e in caso di un qualsiasi errore, non blocca
    lo script ma restuirà FALSE.

    Questo metodo di compressione, come ho detto in precedenza, non è visualizzabile
    con i programmi di gestione archivi, ma esiste la funzione [URL='http://it.php.net/gzencode']gzencode()
    che permette di farlo.

    Esistono inoltre altri tipi di comrpessione GZ, Come quello DEFLATE:
    Per creare archivi così, bisogna utilizzare la funzione [URL='http://it.php.net/gzdeflate']gzdeflate()
    che ha come argomenti i dati da comprimere e il livello di compressione.
    Per poi decomprimere questo tipo di archivio, utilizzaremo la funzione [URL='http://it.php.net/gzinflate']gzinflate()
    che ha come argomenti, i dati e (opzionale) la lunghezza del file.

    Ora scriverò un paio di esempio per quanto riguarda l'utilizzo delle classi, sia
    per i singoli che per gli archivi:

    
    include&#40;"./PaTeR_Class.php"&#41;;
    // Esempio per la creazione di un file singolo
    $singlegz = new gz_single&#40;&#41;;
    $status = $singlegz->compress&#40;".\File_di_origine.txt", "Nuovo_archivio_gz.txt.gz", /* Livello di compressione */&#41;;
    if&#40;!$status&#41; print "Errore durante la creazione dell'archivio gz";
    
    // Esempio per la decompressione dell'archivio gz
    $singlegz = new gz_single&#40;&#41;;
    $status = $singlegz->decompress&#40;"File_gz_da_decomprimere.gz", "Nuovo_file_decompresso.txt"&#41;;
    if&#40;!$status&#41; print "Errore durante la decompressione dell'archivio gz";
    
    // Esempio creazione di un'archivio gz
    $archivegz = new gz_archive&#40;".\Mio_archivio_gz.gz"&#41;;
    $files = array&#40;".\file1.txt", ".\file2.exe", ".\file3.doc"&#41;;
    $status = $archivegz->compress&#40;$files, /* Livello di compressione */&#41;;
    if&#40;!$status&#41; print "Errore durante la creazione dell'archivio gz";
    
    // Esempio di estrazione di un'archivio gz
    $archivegz = new gz_archive&#40;".\Mio_archivio_gz.gz"&#41;;
    $status = $archivegz->decompress&#40;&#41;;
    if&#40;!$status&#41; print "Errore durante la decompressione dell'archivio gz";
    
    

    Con tutto ciò, ho pensato di poter essere stato utile a qualcuno... :stordita:
    Perchè a volte può essere utile comprimere files o stringhe, specialmente quando
    si lavora con file anche abbastanza grossi.
    Ciauuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu...

    :ciauz: