在PHP 中,流過濾器(stream filters)是一種強大的工具,可以在讀取或寫入流時對數據進行實時處理,比如壓縮、加密、編碼或內容替換。當我們處理大文件時,使用合適的流過濾器不僅能減少內存消耗,還能提高處理效率。
這篇文章將介紹如何使用stream_get_filters函數列出系統可用的流過濾器,並基於需求選擇適合大文件處理的過濾器。
stream_get_filters()是一個內置函數,用來獲取當前PHP 環境中註冊的所有流過濾器。它的調用非常簡單:
$filters = stream_get_filters();
print_r($filters);
這會返回一個數組,列出可用的過濾器,例如:
Array
(
[0] => zlib.inflate
[1] => zlib.deflate
[2] => string.rot13
[3] => string.toupper
[4] => string.tolower
[5] => convert.iconv.*
)
其中:
zlib.inflate / zlib.deflate → 用於壓縮和解壓縮(適合大文件壓縮傳輸)。
convert.iconv.* → 用於字符編碼轉換。
string.* → 簡單的字符串操作(通常不適合大文件,因為是逐塊操作,不是流式優化)。
對於大文件處理,我們通常關注兩類過濾器:
?壓縮類(zlib) :能減少磁盤讀寫量。
?編碼轉換類(iconv) :流式轉換字符編碼,適合大文本文件。
示例:壓縮一個大文件內容並寫入新文件
$source = 'large_input.txt';
$destination = 'large_output.gz';
// 打開源文件
$in = fopen($source, 'rb');
// 打開目標文件並附加 zlib.deflate 壓縮過濾器
$out = fopen('compress.zlib://' . $destination, 'wb');
if (!$in || !$out) {
die('無法打開文件');
}
while (!feof($in)) {
$buffer = fread($in, 8192);
fwrite($out, $buffer);
}
fclose($in);
fclose($out);
echo "文件已壓縮並保存為 $destination\n";
注意這裡使用的compress.zlib://協議,它其實底層用的就是zlib.deflate過濾器。
有時你不想使用協議包裝器,而是動態為現有流加過濾器,可以用stream_filter_append :
$fp = fopen('output.txt', 'wb');
$filter = stream_filter_append($fp, 'string.toupper', STREAM_FILTER_WRITE);
fwrite($fp, 'Hello gitbox.net!');
fclose($fp);
// output.txt 中將寫入 HELLO GITBOX.NET!
對於大文件,要避免過多string 系列過濾器,因為它們不一定針對性能優化。推薦優先考慮zlib 、 bzip2 、 iconv等專門設計用於流式處理的過濾器。
如果你不確定哪些過濾器是否可用,可以這樣檢測:
$availableFilters = stream_get_filters();
$needed = ['zlib.deflate', 'convert.iconv.utf-8/cp1251'];
foreach ($needed as $filter) {
$found = false;
foreach ($availableFilters as $available) {
if (stripos($available, $filter) !== false) {
$found = true;
break;
}
}
echo $filter . ': ' . ($found ? '可用' : '不可用') . "\n";
}