如果您想清空文件的内容,请记住,以 w 模式打开文件会自动截断文件,因此,与其这样做……
<?php
$fp = fopen("/tmp/file.txt", "r+");
ftruncate($fp, 0);
fclose($fp);
?>
您可以这样做……
<?php
$fp = fopen("/tmp/file.txt", "w");
fclose($fp);
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
ftruncate — 将文件截断到给定长度
stream
文件指针。
注意:
stream
必须以写入模式打开。
size
要截断到的长度。
注意:
如果
size
大于文件大小,则文件将用空字节扩展。如果
size
小于文件大小,则文件将被截断到该大小。
示例 #1 文件截断示例
<?php
$filename = 'lorem_ipsum.txt';
$handle = fopen($filename, 'r+');
ftruncate($handle, rand(1, filesize($filename)));
rewind($handle);
echo fread($handle, filesize($filename));
fclose($handle);
?>
注意:
文件指针不会改变。
如果您想清空文件的内容,请记住,以 w 模式打开文件会自动截断文件,因此,与其这样做……
<?php
$fp = fopen("/tmp/file.txt", "r+");
ftruncate($fp, 0);
fclose($fp);
?>
您可以这样做……
<?php
$fp = fopen("/tmp/file.txt", "w");
fclose($fp);
?>
ftruncate 后写入
我没有想到我可以在任何地方写入。我以为我会写入文件的开头,但是前 4 个字节会自动填充为 NULL,然后是“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
*/
?>
所以,ftruncate 不仅仅像之前的注释中那样用 NULL 填充空文件。fread 也会用 NULL 填充前导空格。
rc at opelgt dot org 提到的问题似乎完全合乎逻辑。
当指针位于偏移量 4 处并且您截断文件时,指针仍然位于偏移量 4 处。
因此,当您写入() 时,操作系统会用空字节填充前 4 个字节 - PHP 没有问题。它填充空字节是因为磁盘上有数据,需要用零位清除。
尽管这是一个操作系统的问题,为了避免数据损坏,PHP文档应该清楚地说明这一点。此外,如果PHP在截断到更小尺寸后自动将指针的偏移量设置为SEEK_END,以防范错误,那就更好了。
如果你想使用ftruncate但保留文件末尾内容
<?php
function ftruncatestart($filename,$maxfilesize){
$size=filesize($filename);
if ($size<$maxfilesize*1.0) return;
$maxfilesize=$maxfilesize*0.5; //我们不想太频繁地执行此操作…
$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);
}
?>
它不会简单的截断,而是会查找换行符,这样可以避免损坏你的csv或日志文件。但是我不知道这是否会增加你驱动器的读写头压力;)