7

我正在使用 php (1GB+) 中的大型文本文件,我正在使用

file_get_contents("file.txt", NULL, NULL, 100000000,100); 

要从文件中间获取数据,但如果我想将文件中的数据更改为与原始数据不同的更改,我将不得不重新编写整个文件。

如果数据大于原始数据,如何更改文件中的数据(可变长度)而不覆盖数据?我保留了文件中不同数据块及其字节位置的索引。似乎唯一的选择是将x个字节数专用于每条数据,然后如果我想更改它则重写该块......问题在于它会占用比需要更多的空间空字节,写入需要更长的时间......而且仍然无法解决如何“删除”数据,因为文件永远不会缩小大小......我真的需要一些帮助......

如果我为文件中的每条数据使用前缀块,比如 1 mb,那么我想输入的数据100kb只有数据,因为它会覆盖超过第一个专用块...删除它是不可能的...希望这有任何意义...我不是在寻找替代品,我正在寻找在中间写入和更改数据文件,嘿嘿……

更新:是的,我想替换旧数据,但是如果新数据的扩展超过旧数据,我希望将其余数据进一步推入文件中......

考虑一下:0000000HELLODATA00000000 零代表空白空间,什么都没有......现在我想用 SOMETHING 替换 HELLO,现在因为有些东西比 hello 大,简单地写在 hello 的起点会延伸到 hello 并开始覆盖数据.. .因此我希望将数据进一步推入文件中,以便在不覆盖数据的情况下为某些内容腾出空间......呵呵

4

3 回答 3

11

覆盖数据:

$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 modificationfrompoint 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
}
于 2013-05-29T12:11:17.470 回答
3

Another variant of the injectData() function:

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);
}

It copies the end of file (from $position onwards) into a temporary file, seeks back to write the data and stitches everything back up.

于 2013-05-29T13:37:04.033 回答
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);
}
于 2013-05-29T13:25:02.077 回答