在 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";
}