You MUST use rewind() after ftruncate() to replace file content
(PHP 4, PHP 5, PHP 7)
ftruncate — 将文件截断到给定的长度
$handle
, int $size
) : bool
接受文件指针 handle
作为参数,并将文件大小截取为
size
。
handle
文件指针。
Note:
The
handle
must be open for writing.
size
The size to truncate to.
Note:
If
size
is larger than the file then the file is extended with null bytes.If
size
is smaller than the file then the file is truncated to that size.
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
Example #1 File truncation example
<?php
$filename = 'lorem_ipsum.txt';
$handle = fopen($filename, 'r+');
ftruncate($handle, rand(1, filesize($filename)));
rewind($handle);
echo fread($handle, filesize($filename));
fclose($handle);
?>
Note:
The file pointer is not changed.
You MUST use rewind() after ftruncate() to replace file content
If you want to empty a file of it's contents bare in mind that opening a file in w mode truncates the file automatically, so instead of doing...
<?php
$fp = fopen("/tmp/file.txt", "r+");
ftruncate($fp, 0);
fclose($fp);
?>
You can just do...
<?php
$fp = fopen("/tmp/file.txt", "w");
fclose($fp);
?>
If you want to ftruncate but keep the end:
<?php
function ftruncatestart($filename,$maxfilesize){
$size=filesize($filename);
if ($size<$maxfilesize*1.0) return;
$maxfilesize=$maxfilesize*0.5; //we don't want to do it too often...
$fh=fopen($filename,"r+");
$start=ftell($fh);
fseek($fh,-$maxfilesize,SEEK_END);
$drop=fgets($fh);
$offset=ftell($fh);
for ($x=0;$x<$maxfilesize;$x++){
fseek($fh,$x+$offset);
$c=fgetc($fh);
fseek($fh,$x);
fwrite($fh,$c);
}
ftruncate($fh,$maxfilesize-strlen($drop));
fclose($fh);
}
?>
It will not just cut it but search for a newline so you avoid corrupting your csv or logfiles. But I don't know if you will stress the reading head of your drive. ;)
Writing after ftruncate
I didnt expect that I can write in the middle of nowhere. I thought that I would write at the beginning of the file but the first 4 bytes were filled automatically with NULLs followed by "56":
<?php
$str1 = 1234;
$str2 = 56;
$datei = "test.txt";
$dh = fopen($datei,"w");
fwrite($dh, $str1);
fclose($dh);
$dh = fopen ($datei,"r+");
echo "content: ".fread($dh, filesize($datei))."<br>";
echo "pointer after fread at: ".ftell($dh)."<br>";
ftruncate($dh, 0);
echo "pointer after truncate at: ".ftell($dh)."<br>";
fwrite($dh, $str2);
echo "pointer after fwrite at: ".ftell($dh)."<br>";
rewind($dh);
echo "pointer after rewind at: ".ftell($dh)."<br>";
$str = fread($dh, 6);
echo "content: $str<br>in ASCII: ";
for($i = 0; $i < 6; $i++)
echo ord($str{$i})."-";
fclose($dh);
/*
OUTPUT:
content: 1234
pointer after fread at: 4
pointer after truncate at: 4
pointer after fwrite at: 6
pointer after rewind at: 0
content: 56
in ASCII: 0-0-0-0-53-54
*/
?>
So not only ftruncate is filling an empty file up with NULLs as in the note before. Fread is filling leading space with NULLs too.