如何在`rename`之前的`fopen`仍然使用PHP讀取舊內容

下面的代碼打開一個特定文件的文件描述符($fp),然后我覆蓋該文件(使用rename),稍后我使用fread讀取該文件的內容。令我驚訝的是,當使用fread讀取文件時,它仍然指向原始文件的內容(在被覆蓋之前)!這是怎么發生的?我認為只有當fopen制作了一個完整的文件副本,以便以后可以讀取時,這才有可能,但我不敢相信fopen制作了整個文件副本,因為這將是非常不夠的。

<?php

$fileA = "fileA.txt";
$fileB = "fileB.txt";

file_put_contents($fileA,"aaaaaaaaaaaaaa111111",LOCK_EX);
file_put_contents($fileB,"bbbbbbbbbbbbbb222222",LOCK_EX);

$fp = fopen($fileA,"r");

rename($fileB,$fileA);

echo fread($fp,10000);

?>

令人驚訝的是,上面的代碼輸出aaaaaaaaaaaaaa111111,但它應該輸出bbbbbbbbbbbbbb222222。如果在fread之前,我使用fclose并重新打開文件,它會按預期工作(顯示新內容)。

我的問題是,PHP如何仍然能夠顯示已被覆蓋的原始文件的內容!我簡直不敢相信,當我調用fopen時,PHP竟然復制了整個文件。

上述代碼在Linux上運行良好,但在Windows上無法運行,因為在已使用fopen打開的文件上使用rename會拋出錯誤——在Linux上,這似乎沒問題,沒有錯誤。

? 最佳回答:

請注意,代碼(針對您的情況)在一定程度上依賴于操作系統

例如,如果我們稍微更改重命名語句以顯示重命名函數結果(如評論員所建議的):

echo "checking result of rename:" . rename($fileB,$fileA);

使代碼變為:

<?php

$fileA = "fileA.txt";
$fileB = "fileB.txt";

file_put_contents($fileA,"aaaaaaaaaaaaaa111111",LOCK_EX);
file_put_contents($fileB,"bbbbbbbbbbbbbb222222",LOCK_EX);


$fp = fopen($fileA,"r");

echo "checking result of rename:" . rename($fileB,$fileA);
echo "<br>";


echo fread($fp,10000);

?>

那么在Windows操作系統上運行PHP腳本時,結果(比如在XAMPP上運行)將是:

對于相同的代碼,如果在linux操作系統上運行相同的PHP腳本,結果將是:

因此,對于在Win操作系統上運行的PHP腳本,由于操作系統禁止重命名操作(當文件“打開”時),因此在觸發PHP重命名函數時不會進行文件覆蓋操作,因此系統會忠實地顯示原始fileA.txt的內容,即“aaaaaaaaaa 111111”。(是的,我已經檢查過了,重命名操作失敗,那里還有兩個TXT文件)

對于在linux操作系統上運行的PHP腳本,重命名操作將成功(即使當fileA.txt被fopen“打開”時),因此PHP會用數據“bbbbbbbbbb 222222”用fileB.txt的內容覆蓋原始的fileA.txt。

然而,您觀察到的仍然是正確的,因為即使對于在linux操作系統上運行的PHP,當重命名操作后fileA.txt已經具有數據“bbbbbbbbbb bbbbbb 222222”時,系統也會顯示“aaaaaaaaaa 111111”。

我已經測試過了——這與fread操作之前的重命名操作中是否存在I/O延遲無關。因此,即使我在fread語句前添加一行“sleep(10)”,系統仍將顯示數據“aaaaaaaaaa 111111”,即使fileA.txt消失并替換為fileB.txt

因此,對于這種情況,即使您使用重命名函數“覆蓋”原始文件的數據,文件句柄(在linux上)仍將指向原始文件數據。“overwrite”操作(如PHP官方文檔中所述)告訴您操作的結果。但實際上文件句柄仍然指向原始數據流(在I/O上),因此系統仍然顯示舊數據。

當然,解決方法之一是刷新文件句柄,例如:

  1. 在重命名語句后關閉文件句柄
  2. Re-open fileA通過fopen獲取新的文件句柄

因此,以下內容對于在Linux操作系統上運行的PHP是有益的:(它將顯示“bbbbbbbbbb 222222”)

<?php

$fileA = "fileA.txt";
$fileB = "fileB.txt";

file_put_contents($fileA,"aaaaaaaaaaaaaa111111",LOCK_EX);
file_put_contents($fileB,"bbbbbbbbbbbbbb222222",LOCK_EX);


$fp = fopen($fileA,"r");

echo "checking result of rename:" . rename($fileB,$fileA);
echo "<br>";

fclose($fp);
$fp = fopen($fileA,"r");

echo fread($fp,10000);

?>

主站蜘蛛池模板: 亚洲一区二区三区久久| 国产一区二区免费视频| 一区二区三区国产精品| 日本一区中文字幕日本一二三区视频 | 国产av熟女一区二区三区| 无码人妻精品一区二区蜜桃网站 | 国产在线无码视频一区二区三区 | 国产区精品一区二区不卡中文| 少妇一晚三次一区二区三区| 国产在线观看一区二区三区精品 | 农村人乱弄一区二区| 日本高清无卡码一区二区久久| 国产精品一区二区久久精品涩爱| 无人码一区二区三区视频| 久久久久久人妻一区二区三区| 色偷偷一区二区无码视频| 久久精品国产一区二区三区不卡| 国内精品视频一区二区三区八戒| 蜜臀Av午夜一区二区三区| 国产伦精品一区二区三区| 精品aⅴ一区二区三区| 无码精品人妻一区二区三区AV| 亚洲午夜一区二区三区| 国产午夜精品一区二区三区| 国产伦精品一区二区免费 | 国产精品成人一区二区| 亚洲av无码天堂一区二区三区| 亚洲美女高清一区二区三区| 国产一区二区三区国产精品| 一区二区传媒有限公司| 精品少妇人妻AV一区二区| AV天堂午夜精品一区二区三区| 国模一区二区三区| 韩国一区二区三区视频| 人成精品视频三区二区一区 | 无码人妻精品一区二区在线视频 | 久久亚洲AV午夜福利精品一区| 超清无码一区二区三区| 国产精品视频一区二区噜噜 | 麻豆精品一区二区综合av| 一区在线观看视频|