PHP Conference Japan 2024

gzinflate

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

gzinflate解壓縮一個壓縮後的字串

說明

gzinflate(字串 $data, 整數 $max_length = 0): 字串|false

這個函式會解壓縮一個壓縮過的字串。

參數

data

經由 gzdeflate() 壓縮的資料。

max_length

已解碼資料的最大長度。

回傳值

原始未壓縮的資料,或錯誤時傳回 false

如果未壓縮的資料長度超過壓縮輸入 data 的 32768 倍,或者超過可選參數 max_length(除非 max_length0),則此函式將返回錯誤。

範例

範例 #1 gzinflate() 範例

<?php
$compressed
= gzdeflate('Compress me', 9);
$uncompressed = gzinflate($compressed);
echo
$uncompressed;
?>

參見

新增筆記

使用者貢獻的筆記 10 則筆記

anonymous at dekho-ji dot com
11 年前
在 PHP 程式碼中解碼/解壓縮接收到的 HTTP POST 資料,請求資料來自 Java/Android 應用程式,透過 HTTP POST GZIP/DEFLATE 壓縮格式傳送。

1) 使用 Java Android 應用程式中的 DeflaterOutputStream java 類別將資料傳送到 PHP,並在 PHP 中接收,如下所示
echo gzinflate( substr($HTTP_RAW_POST_DATA,2,-4) ) . PHP_EOL . PHP_EOL;

2) 使用 Java Android 應用程式中的 GZIPOutputStream java 類別將資料傳送到 PHP,並在 PHP 程式碼中接收,如下所示
echo gzinflate( substr($HTTP_RAW_POST_DATA,10,-8) ) . PHP_EOL . PHP_EOL;

從 Java Android 端(API level 10+)以 DEFLATE 壓縮格式傳送資料
String body = "Lorem ipsum shizzle ma nizle";
URL url = new URL("http://www.url.com/postthisdata.php");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setRequestProperty("Content-encoding", "deflate");
conn.setRequestProperty("Content-type", "application/octet-stream");
DeflaterOutputStream dos = new DeflaterOutputStream(
conn.getOutputStream());
dos.write(body.getBytes());
dos.flush();
dos.close();
BufferedReader in = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String decodedString = "";
while ((decodedString = in.readLine()) != null) {
Log.e("dump",decodedString);
}
in.close();

在 PHP 端(v 5.3.1),用於解壓縮此 DEFLATE 資料的程式碼如下
echo substr($HTTP_RAW_POST_DATA,2,-4);

從 Java Android 端(API level 10+)以 GZIP 壓縮格式傳送資料

String body1 = "Lorem ipsum shizzle ma nizle";
URL url1 = new URL("http://www.url.com/postthisdata.php");
URLConnection conn1 = url1.openConnection();
conn1.setDoOutput(true);
conn1.setRequestProperty("Content-encoding", "gzip");
conn1.setRequestProperty("Content-type", "application/octet-stream");
GZIPOutputStream dos1 = new GZIPOutputStream(conn1.getOutputStream());
dos1.write(body1.getBytes());
dos1.flush();
dos1.close();
BufferedReader in1 = new BufferedReader(new InputStreamReader(
conn1.getInputStream()));
String decodedString1 = ""; // 字串 decodedString1 = ""
while ((decodedString1 = in1.readLine()) != null) { // 當 (decodedString1 = in1.readLine()) 不為 null 時
Log.e("dump",decodedString1); // 輸出錯誤訊息,標籤為 "dump",訊息為 decodedString1
}
in1.close(); // 關閉 in1

On PHP side (v 5.3.1), code for decompressing this GZIP data will be // 在 PHP 端 (版本 5.3.1),解壓縮 GZIP 資料的程式碼如下
echo substr($HTTP_RAW_POST_DATA,10,-8); // 輸出 $HTTP_RAW_POST_DATA 字串,從第 10 個字元開始,到倒數第 8 個字元

Useful PHP code for printing out compressed data using all available formats. // 使用所有可用格式輸出壓縮資料的實用 PHP 程式碼。

$data = "Lorem ipsum shizzle ma nizle"; // $data = "Lorem ipsum shizzle ma nizle"
echo "\n\n\n"; // 輸出三個換行符號
for($i=-1;$i<=9;$i++) // $i 從 -1 迴圈到 9
echo chunk_split(strtoupper(bin2hex(gzcompress($data,$i))),2," ") . PHP_EOL . PHP_EOL; // 使用 gzcompress 壓縮 $data,並以指定壓縮等級 $i 進行壓縮,然後將結果轉換為十六進位字串,再將字串以兩個字元為一組,用空格隔開,最後輸出兩個換行符號
echo "\n\n\n"; // 輸出三個換行符號
for($i=-1;$i<=9;$i++) // $i 從 -1 迴圈到 9
echo chunk_split(strtoupper(bin2hex(gzdeflate($data,$i))),2," ") . PHP_EOL . PHP_EOL; // 使用 gzdeflate 壓縮 $data (同上)
echo "\n\n\n"; // 輸出三個換行符號
for($i=-1;$i<=9;$i++) // $i 從 -1 迴圈到 9
echo chunk_split(strtoupper(bin2hex(gzencode($data,$i,FORCE_GZIP))),2," ") . PHP_EOL . PHP_EOL; // 使用 gzencode 並強制使用 GZIP 壓縮 $data (同上)
echo "\n\n\n"; // 輸出三個換行符號
for($i=-1;$i<=9;$i++) // $i 從 -1 迴圈到 9
echo chunk_split(strtoupper(bin2hex(gzencode($data,$i,FORCE_DEFLATE))),2," ") . PHP_EOL . PHP_EOL; // 使用 gzencode 並強制使用 DEFLATE 壓縮 $data (同上)
echo "\n\n\n"; // 輸出三個換行符號

Hope this helps. Please ThumbsUp if this saved you a lot of effort and time. // 希望這有幫助。如果這幫你省了很多力氣和時間,請按讚。
felix dot klee at inka dot de // felix.klee@inka.de 的連結
11 年前
The code below illustrates usage of the second parameter, in particular to protect against fatal out-of-memory errors. It outputs // 以下程式碼說明了第二個參數的用法,特別是用於防止致命的記憶體不足錯誤。它會輸出

1000000
1000000
error // 錯誤

Tested with PHP 5.3 on 32bit Linux. // 在 32 位元 Linux 系統上的 PHP 5.3 測試過。

<?php

function tryToGzinflate($deflatedData, $maxLen = 0) {
$data = gzinflate($deflatedData, $maxLen);
if (
$data === false)
echo
'error<br>';
else
echo
strlen($data).'<br>';
}

// 隨機資料:
$data = '';
for (
$i = 0; $i < 1000000; $i++)
$data .= chr(mt_rand(97, 122)); // a-z

$deflatedData = gzdeflate($data);

ini_set('memory_limit', '5M'); // 充足的記憶體
tryToGzinflate($deflatedData);
tryToGzinflate($deflatedData, strlen($data));

ini_set('memory_limit', '100'); // 記憶體不足
tryToGzinflate($deflatedData, 100);
tryToGzinflate($deflatedData); // 造成致命的記憶體不足錯誤
?> // PHP 程式碼範例,示範 tryToGzinflate 函數的使用,以及如何透過 $maxLen 參數避免記憶體不足錯誤。程式碼產生隨機資料,壓縮後嘗試解壓縮,並設定不同的記憶體限制來測試。
vitall at ua dot fm // vitall@ua.fm 的連結
15 years ago // 15 年前
適用於 gzip 和分塊資料的正確函式,尤其是在收到「Content-Encoding: gzip」和「Transfer-Encoding: chunked」標頭時

<?php
function decode_gzip($h,$d,$rn="\r\n"){
if (isset(
$h['Transfer-Encoding'])){
$lrn = strlen($rn);
$str = '';
$ofs=0;
do{
$p = strpos($d,$rn,$ofs);
$len = hexdec(substr($d,$ofs,$p-$ofs));
$str .= substr($d,$p+$lrn,$len);
$ofs = $p+$lrn*2+$len;
}while (
$d[$ofs]!=='0');
$d=$str;
}
if (isset(
$h['Content-Encoding'])) $d = gzinflate(substr($d,10));
return
$d;
}
?>

請享用!
Steven Lustig
14 年前
您可以使用這個方法,透過去除前 10 個位元組來解壓縮來自 Linux 命令列 gzip 的字串。

<?php
$inflatedOutput
= gzinflate(substr($output, 10, -8));
?>
boris at gamate dot com
21 年前
當擷取經 mod_gzip 壓縮的內容,並使用 gzinflate() 來解碼資料時,請務必去除擷取內容的前 10 個字元。

<?php $dec = gzinflate(substr($enc,10)); ?>
patatraboum at free dot fr
17 年前
一些 gz 字串會去除標頭並返回已解壓縮的內容。
它實際上會處理 gz 的一些第一個成員。
更多 gzdecode 的細節與改進,請參考 rfc1952:http://www.faqs.org/rfcs/rfc1952.html

<?php
function gzBody($gzData){
if(
substr($gzData,0,3)=="\x1f\x8b\x08"){
$i=10;
$flg=ord(substr($gzData,3,1));
if(
$flg>0){
if(
$flg&4){
list(
$xlen)=unpack('v',substr($gzData,$i,2));
$i=$i+2+$xlen;
}
if(
$flg&8) $i=strpos($gzData,"\0",$i)+1;
if(
$flg&16) $i=strpos($gzData,"\0",$i)+1;
if(
$flg&2) $i=$i+2;
}
return
gzinflate(substr($gzData,$i,-8));
}
else return
false;
}
?>
spikeles_ at hotmail dot com
18 年前
這個可以用來解壓縮由 Java 類別 java.util.zip.Deflater 壓縮的串流,但你必須先移除開頭的 2 個位元組。(很像上面的註解)

<?php $result = gzinflate(substr($compressedData, 2)); ?>
niblett at gmail dot com
12 年前
另一種方法,可偵測是否有可選的檔名標頭
<?php
function gzdecode($data) {

// 檢查 FLG 中是否設定了檔名欄位,位於第 4 個位元組
$hex = bin2hex($data);

$flg = (int)hexdec(substr($hex, 6, 2));

// 移除標頭
$hex = substr($hex, 20);

$ret = '';
if ( (
$flg & 0x8) == 8 ){
print
"ello";
for (
$i = 0; $i < strlen($hex); $i += 2 ){
$value = substr($hex, $i, 2);
if (
$value == '00' ){
$ret = substr($hex, ($i+2));
break;
}
}
}
return
gzinflate(pack('H*', $ret));
}
?>
akniep at rayo dot info
11 年前
使用選用的第二個參數 $length 時要小心!
在我們的測試中,至少在某些情況下,我們無法確定這個參數的實際用途,此外,它還會導致腳本無法解壓縮數據或因記憶體問題而崩潰。

範例
當嘗試解壓縮來自網站的壓縮數據時,我們實際上找不到 $length 的值(0 除外)來讓 gzinflate 正常工作... 而沒有第二個參數(或將其設定為 0)時,gzinflate 卻能完美運作。

<?php
// -----------------------------------------------------------------------
// 測試 1 運作正常,記憶體尖峰使用量:壓縮前:24.787 kB;壓縮後:24.844 kB。
gzinflate( substr($deflated_body, 10) );

// -----------------------------------------------------------------------
// 以下三個測試皆出現警告。記憶體尖峰使用量:壓縮前:24.787 kB;壓縮後:298.262 kB。
gzinflate( substr($deflated_body, 10), 200 * strlen($deflated_body) );
gzinflate( substr($deflated_body, 10), 32768 * strlen($deflated_body) );
gzinflate( substr($deflated_body, 10), 11000 );
gzinflate( substr($deflated_body, 10), 280000000 ); // PHP 記憶體限制設定為 300MB (memory_limit=300M)
=>
警告: gzinflate() [function.gzinflate]: 記憶體不足 [...]

// -----------------------------------------------------------------------
// 最後一個測試出現致命錯誤。記憶體尖峰使用量:壓縮前:24.787 kB;壓縮後:? (> 300M)。
gzinflate( substr($deflated_body, 10), 300000000 ); // PHP 記憶體限制設定為 300MB (memory_limit=300M)
=>
致命錯誤: 允許的記憶體大小 314572800 位元組已耗盡 (嘗試分配 300000000 位元組) in
?>

簡而言之:我們無法在某些情況下確定第二個參數的實際用途。
使用第二個參數 $length 時要小心!
John
16 年前
當擷取經 mod_deflate gzip 壓縮的內容,並使用 gzinflate() 解碼資料時,請務必從擷取的內容中移除前 11 個字元。

<?php $dec = gzinflate(substr($enc,11)); ?>
To Top