如果您想清空文件的内容,请记住,以 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,那将非常棒,这样可以防范错误。
如果您想要截断文件但保留结尾部分
<?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 或日志文件。但我不知道这是否会给您的驱动器读写头带来压力。;)