我正在处理php(1GB +)中的大文本文件,我正在使用
file_get_contents("file.txt", NULL, NULL, 100000000,100);
要从文件中间获取数据,但如果我想将文件中的数据更改为与原始数据不同的更改,我将不得不重新编写整个文件。
如果数据大于原始数据,如何更改文件中的数据(可变长度)而不覆盖数据?我保留文件中不同数据块的索引及其字节位置。似乎唯一的选择是为每个数据分配x个字节,然后如果我想改变它就重写那个块......这个问题是它会占用比仅需要更多的空间null字节,写入需要更长时间......而且仍然无法解决如何“删除”数据,因为文件的大小永远不会缩小......我真的需要一些帮助......
如果我对文件中的每个数据使用了前缀块,例如1 mb,那么我想输入仅为100kb
的数据,该条目将占用10倍实际需要的空间,并且该条目可能永远不会被更改为超过1mb的数据,因为它会覆盖超过第一个专用块...删除它是不可能的...希望这有任何意义......我不是在寻找替代方案,我期待在文件中间写入和更改数据,呵呵......
更新:是的,我想替换旧数据,但如果新数据扩展的内容超过旧数据,我希望将其余数据推送到文件中......
考虑这个:0000000HELLODATA00000000 零代表空的空间,什么都没有...现在我想用SOMETHING取代HELLO,现在因为有些东西比你好,只需在hello的起点写入就会延伸到你好并开始覆盖数据......因此我会喜欢将DATA推进到文件中,为SOMETHING腾出空间而不覆盖数据......呵呵
答案 0 :(得分:10)
覆盖数据:
$fp = fopen("file.txt", "rw+");
fseek($fp, 100000000); // move to the position
fwrite($fp, $string, 100); // Overwrite the data in this position
fclose($fp);
注入数据
这很棘手,因为您必须rewrite
该文件。可以使用partial modification
中的point of injection
而不是整个文件
$string = "###INJECT THIS DATA ##### \n";
injectData("file.txt", $string, 100000000);
使用的功能
function injectData($file, $data, $position) {
$fpFile = fopen($file, "rw+");
$fpTemp = fopen('php://temp', "rw+");
$len = stream_copy_to_stream($fpFile, $fpTemp); // make a copy
fseek($fpFile, $position); // move to the position
fseek($fpTemp, $position); // move to the position
fwrite($fpFile, $data); // Add the data
stream_copy_to_stream($fpTemp, $fpFile); // @Jack
fclose($fpFile); // close file
fclose($fpTemp); // close tmp
}
答案 1 :(得分:3)
injectData()
函数的另一种变体:
function injectData($file, $data, $position)
{
$temp = fopen('php://temp', "rw+");
$fd = fopen($file, 'r+b');
fseek($fd, $position);
stream_copy_to_stream($fd, $temp); // copy end
fseek($fd, $position); // seek back
fwrite($fd, $data); // write data
rewind($temp);
stream_copy_to_stream($temp, $fd); // stich end on again
fclose($temp);
fclose($fd);
}
它将文件末尾(从$position
开始)复制到一个临时文件中,回过头来编写数据并将所有内容重新拼接起来。
答案 2 :(得分:2)
关于Baba答案的一个变体,不确定在处理更大的文件时它是否会更有效:
function injectData($file, $data, $position) {
$fpFile = fopen($file, "rw+");
$fpTemp = fopen('php://temp', "rw+");
stream_copy_to_stream($fpFile, $fpTemp, $position);
fwrite($fpTemp, $data);
stream_copy_to_stream($fpFile, $fpTemp, -1, $position);
rewind($fpFile);
rewind($fpTemp);
stream_copy_to_stream($fpTemp, $fpFile);
fclose($fpFile);
fclose($fpTemp);
}
injectData('testFile.txt', 'JKL', 3);
我的早期方法的变体,它消除了一个stream_copy_to_stream()调用,所以应该更快一点:
function injectData3($file, $data, $position) {
$fpFile = fopen($file, "rw+");
$fpTemp = fopen('php://temp', "rw+");
stream_copy_to_stream($fpFile, $fpTemp, -1, $position);
fseek($fpFile, $position);
fwrite($fpFile, $data);
rewind($fpTemp);
stream_copy_to_stream($fpTemp, $fpFile);
fclose($fpFile);
fclose($fpTemp);
}