Reputation: 15847
I have
$bytesCount = file_put_contents( "somefile.log", "some text\n", FILE_APPEND | LOCK_EX );
What happens if another process is writing** on somefile.log
?
Does file_put_contents
fails with a runtime error ?
Does if fails with $bytesCount === false
Or does does it pause the script until the file is unlocked and then performs the write operation?
(**) or more generally another process has an exclusive lock on the file
[ I'm on a *nix
platform with php 5.6 ]
Upvotes: 0
Views: 18175
Reputation: 15847
When file_put_contents
attempts to write on a locked file waits until the file is unlocked then performs the write and returns the number of bytes written.
Proof:
I wrote a simple two-scripts test:
the first script writes a 100MB file (on a slow USB2-connected drive);
the second script appends a short string to the same file.
The core of the two scripts are these four lines:
echo Milliseconds() . ": Start writing file on file\n";
$bytesCount = file_put_contents( "/Volumes/myHD/somefile.txt", $buffer, FILE_APPEND | LOCK_EX );
var_export( $bytesCount );
echo "\n" . Milliseconds() . ": Done writing on file\n";
Where Milliseconds()
is a function that returns the current unix timestamp in milliseconds.
In the first script $buffer
is a 100MB string, in the second script $buffer = "MORE-DATA\n";
Running the first script and quickly starting the second one result in this output:
Script 1:
$ php test1.php
1481892766645: Start writing file on file
100000000
1481892769680: Done writing on file
$
Script 2:
$ php test2.php
1481892766831: Start writing file on locked file
10
1481892769909: Done writing file on locked file
$
Note that:
the second script attempted writing 186 ms after the first one but before the second script was done writing. So the second script actually accessed a locked file.
the second script termiated writing 229 ms after the first one
Checking the result after both scripts terminated execution:
$ stat -f%z /Volumes/myHD/somefile.txt
100000010
$
10MB + 10 bytes were written
$ tail -c 20 /Volumes/myHD/somefile.txt
0123456789MORE-DATA
$
The second script actually appended the string at the end of the file
Upvotes: 2
Reputation: 116
It should be obvious that this should only be used if you're making one write, if you are writing multiple times to the same file you should handle it yourself with fopen and fwrite, the fclose when you are done writing.
Benchmark below:
file_put_contents() for 1,000,000 writes - average of 3 benchmarks:
real 0m3.932s user 0m2.487s sys 0m1.437s
fopen() fwrite() for 1,000,000 writes, fclose() - average of 3 benchmarks:
real 0m2.265s user 0m1.819s sys 0m0.445s
For overwriting when using ftp, this is helpful:
/* create a stream context telling PHP to overwrite the file */
$options = array('ftp' => array('overwrite' => true));
$stream = stream_context_create($options);
http://php.net/manual/en/function.file-put-contents.php
Upvotes: 0