* Reading a BZIP2 file can be tricky, and I never seen a complete example of
* code that account for any possible failure that may happen accessing a file
* in general, and decoding compressed data in this specific case.
* The example that follows is my attempt to address this gap.
* Some things that worth noting are:
* - Encoding/decoding errors must be detected with bzerrno().
* - bzopen() may fail returning FALSE if the file cannot be created or read,
* but succeeds also if the file is not properly encoded.
* - bzread() may fail returning FALSE if it fails reading from the source, but
* it returns the empty string on end of file and on encoding error.
* - bzread() may still return corrupted data with no error whatsoever until the
* BZIP2 algo encounters the first hash code, so data retrieved cannot be
* trusted until the very end of the file has been reached.
*/
// Safety first:error_reporting(-1);// On error, set $php_errormsg:ini_set("track_errors","1");/**
* Reads and displays on stdout the content of a BZIP2 compressed file with
* full error detection.
* @param string $fn Filename.
* @return void
*/functiondisplaysBZIP2File($fn)
{
echo"Reading$fn:\n";$bz= @bzopen($fn,"r");
if($bz===FALSE){
echo"ERROR: bzopen() failed:$php_errormsg\n";
return;
}$errno=bzerrno($bz);
if($errno!=0){// May detect "DATA_ERROR_MAGIC" (not a BZIP2 file), or "DATA_ERROR"
// (BZIP2 decoding error) and maybe others BZIP2 errors too.echo"ERROR: bzopen(): BZIP2 decoding failed: ",bzerrstr($bz),"\n";
@bzclose($bz);
return;
}
while(!feof($bz) ) {$s=bzread($bz,100);
if($s===FALSE){
echo"ERROR: bzread() failed:$php_errormsg\n";
@bzclose($bz);
return;
}$errno=bzerrno($bz);
if($errno!=0){// May detect "DATA_ERROR" (BZIP2 decoding error) and maybe others
// BZIP2 errors too.echo"ERROR: bzread(): BZIP2 decoding failed: ",bzerrstr($bz),"\n";
@bzclose($bz);
return;
}
echo"read: ",var_export($s,true),"\n";
}
if( !bzclose($bz) ){
echo"ERROR: bzclose() failed:$php_errormsg\n";
}
}// Target file:$fn="test.bz2";// Test 1: writes and read a good BZIP2 file:file_put_contents($fn,bzcompress("Content of the file."));displaysBZIP2File($fn);// works ok.
// Test 2: invalid content, not a BZIP2 file:file_put_contents($fn,"This ia plain text file, no compression at all!");displaysBZIP2File($fn);// ERROR: bzread(): BZIP2 decoding failed: DATA_ERROR_MAGIC
// Test 3: creates a corrupted BZIP2 file:$plain=str_repeat("Quite random string. ",1000);$compressed=bzcompress($plain);$compressed_corrupted=$compressed;$compressed_corrupted[(int)(strlen($compressed)/2)] ='X';// put random char in middlefile_put_contents($fn,$compressed_corrupted);displaysBZIP2File($fn);// Only after some Kbytes of garbage, it tells:
// ERROR: bzread(): BZIP2 decoding failed: DATA_ERROR
// Safe coding against headache, ever.?>