2009-08-04 19 views
11

Estoy usando una función de descompresión simple (como se ve a continuación) para mis archivos, así que no tengo que descomprimir archivos manualmente antes de que se procesen más.Desempaquetar archivos grandes con gzip en PHP

function uncompress($srcName, $dstName) { 
    $string = implode("", gzfile($srcName)); 
    $fp = fopen($dstName, "w"); 
    fwrite($fp, $string, strlen($string)); 
    fclose($fp); 
} 

El problema es que si el archivo gzip es grande (por ejemplo, 50 MB) la descompresión toma una gran cantidad de memoria RAM para proceso.

La pregunta: ¿puedo analizar un archivo comprimido en fragmentos y seguir obteniendo el resultado correcto? ¿O existe otra forma mejor de manejar el problema de extraer archivos gzip grandes (incluso si lleva unos segundos más)?

Respuesta

41

gzfile() es un método práctico que llama a gzopen, gzread y gzclose.

Así que, sí, puede hacer manualmente el gzopen y descomprimir el archivo en fragmentos.

Esto descomprimir el archivo en trozos de 4 KB:

function uncompress($srcName, $dstName) { 
    $sfp = gzopen($srcName, "rb"); 
    $fp = fopen($dstName, "w"); 

    while (!gzeof($sfp)) { 
     $string = gzread($sfp, 4096); 
     fwrite($fp, $string, strlen($string)); 
    } 
    gzclose($sfp); 
    fclose($fp); 
} 
+3

¡Dulce! Probado en un archivo de 1 MB gzip que extrae a 48MB - antes: Tiempo de proceso: 12.1447s, el uso de memoria de pico: 96512kB - Su solución: Tiempo de proceso: 0.6705s, Pico de uso de la memoria: 256 kB Gracias :) Usted puede – Lukas

+0

obtener un mejor rendimiento ajustando el número al final de la llamada gzread. No lo he intentado sin embargo. – Powerlord

+0

20 veces mejor es lo suficientemente bueno, y seguirá siendo lo suficientemente bueno durante mucho tiempo. Tendría que estar muy desesperado o usar grandes archivos para tratar de modificar esto :) – Lukas

1

tratan con

function uncompress($srcName, $dstName) { 
    $fp = fopen($dstName, "w"); 
    fwrite($fp, implode("", gzfile($srcName))); 
    fclose($fp); 
} 

parámetro $ longitud es opcional.

+0

Parece que este enfoque hace lo mismo que el enfoque original con una gran cantidad de memoria. El archivo completo se lee y se guarda en la memoria. – Lukas

+0

no se cargan en un archivo de datos variables (similar a la transmisión). no es un modelo de objeto donde cargar la cadena del objeto. Este ejemplo no afecta a "php_value memory_limit". su ejemplo afecta a esta variable en el archivo "php.ini". –

1

Si usted está en un servidor Linux, tienen los privilegies necesarios para ejecutar comandos y se instala el comando gzip, podría intentar llamar con algo como shell_exec

algo un poco como esta, supongo, sería do:

shell_exec('gzip -d your_file.gz'); 

De esta manera, el archivo no se descomprimiría por PHP.


Como comentario:

  • Tenga cuidado de que el comando se ejecuta desde (utilizar ot un swith de decir "descomprimir a que directorio")
  • Es posible que desee echar un vistazo en escapeshellarg también ;-)
+0

Gracias, tengo acceso de shell, pero todavía tengo que aprender a usarlo. – Lukas

0

Como se mencionó maliayas, que puede conducir a un error. Experimenté una caída inesperada del ciclo while, pero el archivo gz se ha descomprimido con éxito. Todo el código se ve así y funciona mejor para mí:

function gzDecompressFile($srcName, $dstName) { 
    $error = false; 

    if($file = gzopen($srcName, 'rb')) { // open gz file 

     $out_file = fopen($dstName, 'wb'); // open destination file 

     while (($string = gzread($file, 4096)) != '') { // read 4kb at a time 
      if(!fwrite($out_file, $string)) { // check if writing was successful 
       $error = true; 
      } 
     } 

     // close files 
     fclose($out_file); 
     gzclose($file);  

    } else { 
     $error = true; 
    } 

    if ($error) 
     return false; 
    else 
     return true; 
} 
Cuestiones relacionadas