Aggiornamento: Dopo aver terminato la mia funzione, ho avuto il tempo di confrontarlo. Ho usato un file di grandi dimensioni 1GB
per il test ma i risultati sono insoddisfacenti: |
Sì, l'allocazione memoria di picco è significativamente minore:
- soluzione standard: 1,86 GB
- personalizzato soluzione: 653 KB (4096 byte buffersize)
Ma rispetto al seguente soluzione c'è solo un leggero aumento delle prestazioni:
ini_set('memory_limit', -1);
file_put_contents(
'test.txt',
str_replace('the', 'teh', file_get_contents('test.txt'))
);
la scrittura t sopra ha richiesto ~ 16 secondi, la soluzione personalizzata ha richiesto ~ 13 secondi.
Riprendi: la soluzione di custodia è leggermente più veloce su file di grandi dimensioni e consuma molta meno memoria (!!!).
Inoltre, se si desidera eseguire questo in un ambiente di server Web, la soluzione personalizzata è migliore in quanto molti script concorrenti potrebbero consumare l'intera memoria disponibile del sistema.
risposta originale:
L'unica cosa che mi viene in mente, è quello di leggere il file in blocchi che si inseriscono i file system Dimensione blocco e scrivere il contenuto o modificati i contenuti di nuovo ad un file temporaneo . Dopo aver terminato l'elaborazione, utilizzare rename()
per sovrascrivere il file originale.
Ciò ridurrebbe il picco di memoria e dovrebbe essere significativamente più veloce se il file è molto grande.
Nota: su un sistema Linux è possibile ottenere la dimensione del blocco del file system utilizzando:
sudo dumpe2fs /dev/yourdev | grep 'Block size'
ho ottenuto 4096
Ecco che arriva la funzione:
function freplace($search, $replace, $filename, $buffersize = 4096) {
$fd1 = fopen($filename, 'r');
if(!is_resource($fd1)) {
die('error opening file');
}
// the tempfile can be anywhere but on the same partition as the original
$tmpfile = tempnam('.', uniqid());
$fd2 = fopen($tmpfile, 'w+');
// we store len(search) -1 chars from the end of the buffer on each loop
// this is the maximum chars of the search string that can be on the
// border between two buffers
$tmp = '';
while(!feof($fd1)) {
$buffer = fread($fd1, $buffersize);
// prepend the rest from last one
$buffer = $tmp . $buffer;
// replace
$buffer = str_replace($search, $replace, $buffer);
// store len(search) - 1 chars from the end of the buffer
$tmp = substr($buffer, -1 * (strlen($search)) + 1);
// write processed buffer (minus rest)
fwrite($fd2, $buffer, strlen($buffer) - strlen($tmp));
};
if(!empty($tmp)) {
fwrite($fd2, $tmp);
}
fclose($fd1);
fclose($fd2);
rename($tmpfile, $filename);
}
chiamare in questo modo :
freplace('foo', 'bar', 'test.txt');
"Il migliore" è soggettivo. Dalle ragioni vicine "_Spettiamo che le risposte siano supportate da fatti, riferimenti o competenze specifiche, ma questa domanda probabilmente solleciterà dibattiti, discussioni, sondaggi o discussioni estese." "Considereresti di migliorare la tua domanda selezionando un metodo particolare e spiegando come non soddisfa le tue esigenze?Ciò consentirà di fornire risposte specifiche, piuttosto che soggettive. –
@GeorgeCummins Il tuo commento non si applica qui. Questa è una tipica domanda di programmazione – hek2mgl
@Baba Sei sicuro che i tuoi tentativi siano più veloci di quello [I've supposto] (http://stackoverflow.com/a/16887051/171318)? Nota che un semplice 'rename()' è molto veloce. Preparerà alcuni benchmark :) Si noti inoltre che la ricerca in cui la stringa deve essere sostituita non è nota nella maggior parte degli scenari applicativi – hek2mgl