#php #file-get-contents #flock #file-put-contents
#php #file-get-contents #flock #file-put-contents
Вопрос:
Как функция PHP «file_get_contents ()» обрабатывает запрос, если данный файл записывается? Ожидает ли она завершения процесса записи, а затем считывает файл, или просто не может прочитать файл?
Использует ли функция «file_get_contents ()» функцию «flock ()» по умолчанию?
Комментарии:
1. Зависит от уровня общего доступа, когда файл открыт. Многие текстовые редакторы распознают, когда отображаемый в данный момент файл изменен другим процессом. Итак, да, на самом деле возможно записывать и читать одновременно (хотя, очевидно, не полностью одновременно)
2. @LarsStegelitz, из User1010 и моих тестовых кодов кажется, что «file_get_contents ()» возвращает пустую строку, если данный файл записывается, поэтому я написал функцию «flock_file_get_contents ()» в качестве альтернативы (лучшие решения всегда приветствуются)!
Ответ №1:
Все время записи файла он ничего не возвращает,
import time
with open('output.file', 'wb') as file:
for x in range(30):
file.write(b'Test')
time.sleep(1)
<?php
var_dump(file_get_contents('output.file'));
Вывод string(0) ""
(Вист открыт)
Вывод string(120) "TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest"
после записи
Комментарии:
1. Спасибо за ответ! Я провел свои собственные тесты, и да, кажется, что «file_get_contents ()» возвращает пустую строку во время записи файлов, к сожалению! Я написал функцию «flock_file_get_contents ()» в качестве альтернативы, но если есть лучшие решения, пожалуйста, поделитесь ими здесь!
Ответ №2:
Я провел несколько тестов и, действительно, «file_get_contents ()» не использует «flock ()», и нет никакого способа использовать флаг «LOCK_SH» в качестве альтернативы!
Если файл записывается, «file_get_contents ()» не ожидает в очереди, он считывает файл, а затем возвращает пустую строку!
Я написал функцию «flock_file_get_contents ()» в качестве альтернативы, если файл записывается, он ожидает в очереди, пока процесс записи не завершится, затем он считывает файл!
Лучшие решения всегда приветствуются!
[OBS]:
- Единственное, что мне не нравится в «flock ()», это то, что он не обрабатывает запросы в порядке вызова!
[Отредактировано]:
- Функции «wait_Read_Write_end_of ($File)» (альтернатива)
- функция «flock_file_put_contents ()» (добавлена)
- функция «flock_file_get_contents ()» использует флаг «LOCK_SH» вместо флага «LOCK_EX»!
<?php
$Overwrite_Sleep = 10; //seconds
$flock_GFC_Sleep = 2; //seconds
$File = basename($_SERVER['SCRIPT_FILENAME'], '.php') . ".txt";
if (isset($_POST["Request"])){
if($_POST["Request"] == "Get_File_Content"){echo file_get_contents($File);
}else if ($_POST["Request"] == "flock_Get_File_Content"){echo flock_file_get_contents($File);
}else{
flock_file_put_contents($File, function($F_P){
$File_Content = file_get_contents($F_P);
$File_Content = str_replace("O", "A", $File_Content);
$File_Content = str_replace("p", "t", $File_Content);
$File_Content = str_replace("0", "", $File_Content);
//the below is basically what "file_put_contents()" does, except the "sleep()" part
$File_Handle = fopen($F_P, 'w');
fwrite($File_Handle, $File_Content . sleep($GLOBALS["Overwrite_Sleep"])); //the write process takes some time to finish
fclose($File_Handle);
}, $Return_Message);
echo ($Return_Message == 1) ? "File Overwritten" : "Failed: " . $Return_Message;
}
return;
}
file_put_contents($File, "Oops");
function flock_file_get_contents($File){ //______________________________________________
$File_Handle = fopen("$File", "r");
if(flock($File_Handle, LOCK_SH)){ //on success, this script execution waits here until older scripts in queue unlock the file
$File_Content = file_get_contents($File);
sleep($GLOBALS["flock_GFC_Sleep"]);
flock($File_Handle, LOCK_UN); //unlock the file so new scripts in queue can continue execution
}else{$File_Content = ["flock"=>"Fail"];}
fclose($File_Handle);
return $File_Content;
}
function flock_file_put_contents($File, $Do_This, amp;$Return_Var = ""){ //__________________________________________
$File_Handle = fopen($File, 'r');
if (flock($File_Handle, LOCK_EX)) { //on success, this script execution waits here until older scripts in queue unlock the file
$Do_This($File);
$Return_Message = 1;
flock($File_Handle, LOCK_UN); //unlock the file so new scripts in queue can continue execution
}else{$Return_Message = "flock() Failed";}
fclose($File_Handle);
$Return_Var = $Return_Message;
return $Return_Message;
}
?>
<!DOCTYPE html>
<div style=" float:left;">
<input type="button" value="Overwrite File (Wait <?php echo $Overwrite_Sleep ?> Seconds)" onclick='Test("Overwrite_File", this, Call_Count )'>
<br>
<div id="Response_Overwrite"></div>
</div>
<div style=" float:left; margin-left: 50px; ">
<input type="button" value="file_get_contents()" onclick='Test("Get_File_Content", this, Call_Count )'>
<br>
<div id="Response_Get_Content"></div>
</div>
<div style=" float:left; margin-left: 50px; ">
<input type="button" value="flock_file_get_contents() - Wait <?php echo $flock_GFC_Sleep ?> seconds" onclick='Test("flock_Get_File_Content", this, Call_Count )'>
<br>
<div id="Response_flock_Get_Content"></div>
</div>
<br style=" clear: both;"><br><br>
<?php
echo $_SERVER['SCRIPT_FILENAME'] . "<br><br>";
echo __FILE__ . "<br><br>";
echo basename(__FILE__) . "<br><br>";
echo basename(__FILE__, '.php') . "<br><br>";
echo basename($_SERVER['SCRIPT_FILENAME']) . "<br><br>";
echo basename($_SERVER['SCRIPT_FILENAME'], '.php') . "<br><br>";
?>
<script>
Call_Count = 1;
function Test(Option, El, Call_Count){ //____________________________
//El.disabled = true;
//if (Option === "Overwrite_File"){document.getElementById("Response_Overwrite").innerHTML = "(Please Wait <?php echo $Overwrite_Sleep ?> Seconds) ";
//}else if (Option === "flock_Get_File_Content"){document.getElementById("Response_flock_Get_Content").innerHTML = 'File Content is: ';
//}else{document.getElementById("Response_Get_Content").innerHTML = 'File Content is: '}
var http = new XMLHttpRequest();
http.open('POST', ""); //blank url (send to same page)
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //necessary to send "Request" POST key below to php
http.onreadystatechange = function(){
if (this.readyState === 4) { //"4", request finished and response is ready!
if (Option === "Overwrite_File"){document.getElementById("Response_Overwrite").innerHTML = this.responseText " (Call " Call_Count ")<br>";
}else if (Option === "flock_Get_File_Content"){
document.getElementById("Response_flock_Get_Content").innerHTML = '"' this.responseText '" (Call ' Call_Count ')<br>';
}else{document.getElementById("Response_Get_Content").innerHTML = '"' this.responseText '" (Call ' Call_Count ')<br>';}
El.disabled = false;
}
};
http.send('Request=' Option);
}
</script>