Может ли функция PHP «file_get_contents ()» читать файл во время его записи?

#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 ()», это то, что он не обрабатывает запросы в порядке вызова!

[Отредактировано]:

введите описание изображения здесь

 <?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>