我有一个太大而无法放入内存的文件,我需要从中删除某些字符(控制字符要精确).我目前的功能如下:
$old = fopen($file, 'r');
$new = fopen($tmpFile, 'w');
while (!feof($old)) {
fwrite($new, preg_replace('/[^\P{Cc}\t\r\n]/u', '', fgets($old)));
}
rename($tmpFile, $file);
在大多数情况下,这样做很好.但可能的问题是fgets读取整行.我处理的一些文件实际上是巨大的单行文件,这仍然会导致内存问题.
这可以使用fread来修复,块大小比如8192.但是现在我输入preg_replace的文本可能是截断的多字节字符.
我一直在想如何在保留多字节字符的同时进行预防,但我还没有找到一个好的解决方案.任何帮助都是极好的.
可能解决方案
虽然我以不同的方式解决了这个问题,但我仍然对我原来的问题感到好奇:如何做一个安全的fb?我认为像这样的函数可以工作:
>用fread读取一大块字节
>检查最后一个字节,检查它是否是多字节序列的一部分.如果没有,请停在这里.
>继续读取字节,直到最后一个字节不是多字节序列的一部分,或结束当前序列.
第2步可能会使用一些逻辑like this,但我不熟悉unicode,我知道如何.
解决方法:
我还不能发表评论.但是一个选项就是像你说的那样以块的形式读取数据并使用unpack(‘C *’,$chunk),从那里你可以迭代字节数组并找到你的字符匹配,具体取决于你的字节顺序字节数组.如果在该数组中找到匹配项,请替换或删除这些字节并将字符串pack()返回.
附: :记得重读下一个块中的最后几个字节(这样你就不会有任何与最终替换字符串相关的符号).
我不知道我的解压缩示例是否符合您的偏好,但您可以在这里阅读更多内容:unpack doc
这是另一个指针,如果你使用utf-8:utf-8 encoding,utf-8编码是如何工作的