2024 年日本 PHP 研討會

ftruncate

(PHP 4, PHP 5, PHP 7, PHP 8)

ftruncate將檔案截斷到指定的長度

說明

ftruncate(資源 $stream, 整數 $size): 布林值

使用檔案指標 stream,將檔案截斷至指定的長度 size

參數

stream

檔案指標。

注意事項:

stream 必須以寫入模式開啟。

size

要截斷的大小。

注意事項:

如果 size 大於檔案大小,則檔案會以空位元組 (null bytes) 擴充。

如果 size 小於檔案大小,則檔案會被截斷到該大小。

回傳值

成功時回傳 true,失敗時回傳 false

範例

範例 #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);
?>

備註

注意事項:

檔案指標不會改變。

參見

新增註解

使用者貢獻的註解 5 則註解

44
emailfire at gmail dot com
13 年前
如果您想清空檔案內容,請記住,以 w 模式開啟檔案會自動截斷檔案,因此不必這樣做...

<?php
$fp
= fopen("/tmp/file.txt", "r+");
ftruncate($fp, 0);
fclose($fp);
?>

您可以直接這樣做...

<?php
$fp
= fopen("/tmp/file.txt", "w");
fclose($fp);
?>
20
Julien B.
9 年前
您*必須*在 ftruncate() 之後使用 rewind() 來取代檔案內容
9
rc at opelgt dot org
16 年前
在 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
"內容: ".fread($dh, filesize($datei))."<br>";
echo
"fread 後的指標位置:".ftell($dh)."<br>";
ftruncate($dh, 0);
echo
"truncate 後的指標位置:".ftell($dh)."<br>";
fwrite($dh, $str2);
echo
"fwrite 後的指標位置:".ftell($dh)."<br>";
rewind($dh);
echo
"rewind 後的指標位置:".ftell($dh)."<br>";
$str = fread($dh, 6);
echo
"內容: $str<br>ASCII 碼:";
for(
$i = 0; $i < 6; $i++)
echo
ord($str{$i})."-";
fclose($dh);

/*
輸出:
內容: 1234
fread 後的指標位置:4
truncate 後的指標位置:4
fwrite 後的指標位置:6
rewind 後的指標位置:0
內容: 56
ASCII 碼:0-0-0-0-53-54
*/
?>

因此,不僅 ftruncate 會用 NULL 填滿一個空檔案,如前述說明。fread 也會用 NULL 填滿前導空格。
2
Masoud
4 年前
rc at opelgt dot org 提到的問題似乎完全合乎邏輯。

當指標位於偏移量 4 且您截斷檔案時,指標仍位於偏移量 4。

因此,當您執行 write() 時,作業系統會以前 4 個位元組填入空位元組 - PHP 並沒有錯。它填入空位元組是因為磁碟上有資料,需要用零位元清除。

即使這是作業系統的一個陷阱,為了避免資料損毀,PHP 文件應該清楚地提到這一點。此外,如果 PHP 在截斷到較小尺寸後自動將指標的偏移量設定為 SEEK_END 以防止出錯,那就太好了。
1
eurosat7 at yahoo dot de
13 年前
如果您想使用 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 或日誌檔。 但我不知道這是否會加重您硬碟讀寫頭的負擔 ;)。
To Top