PHP what is the best way to write data to middle of file without rewriting file
Solution 1:
To Overwrite Data :
$fp = fopen("file.txt", "rw+");
fseek($fp, 100000000); // move to the position
fwrite($fp, $string, 100); // Overwrite the data in this position
fclose($fp);
To Inject Data
This is a tricky because you have to rewrite
the file. It can be optimized with partial modification
from point of injection
rather than the whole file
$string = "###INJECT THIS DATA ##### \n";
injectData("file.txt", $string, 100000000);
Function Used
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
}
Solution 2:
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.
Solution 3:
A variant on Baba's answer, not sure if it would be more efficient when working with larger files:
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);
Variant of my earlier method that eliminates one of the stream_copy_to_stream() calls, so should be a shade faster:
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);
}