سؤال

أنا أنحدر من خلفية C وC++ ولكنني ألعب أيضًا ببعض عناصر الويب.جميعنا نحن الأشخاص C (نأمل) نعرف هذا الاتصال feof على FILE* قبل القيام بالقراءة هو خطأ.هذا هو الشيء الذي يلسع المبتدئين في C و C++ في كثير من الأحيان.هل هذا هو الحال أيضًا بالنسبة لتطبيق PHP؟

أعتقد أن السبب هو أن الملف يمكن أن يكون مقبسًا أو أي شيء آخر حيث من المستحيل معرفة الحجم قبل الانتهاء من القراءة.ولكن فقط عن كل مثال PHP (حتى تلك الموجودة في php.net لقد رأيت شيئًا كهذا (وتنطلق الإنذارات في رأسي):

$f = fopen("whatever.txt", "rb");
while(!feof($f)) {
    echo fgets($f);
}
fclose($f);

أعلم أنه من الأفضل كتابة هذا الأمر وتجنب هذه المشكلة:

$f = fopen("whatever.txt", "rb");
while($line = fgets($f)) {
    echo $line;
}
fclose($f);

ولكن ذلك بالإضافة إلى هذه النقطة.لقد حاولت اختبار ما إذا كانت الأمور ستفشل إذا قمت بها "بطريقة خاطئة"، لكنني لم أتمكن من جعلها تتسبب في سلوك غير صحيح.هذا ليس علميًا تمامًا، لكنني اعتقدت أنه يستحق المحاولة.

لذلك، هل من الخطأ الاتصال feof قبل fread في PHP؟

هناك عدة طرق يمكن لـ PHP من خلالها القيام بذلك بشكل مختلف عن إصدار C، لكنني أشعر أن لها جوانب سلبية.

  • يمكن أن يكون لديهم الافتراضي إلى !EOF.يعد هذا دون المستوى الأمثل لأنه قد يكون غير صحيح في بعض الحالات الزاوية.

  • يمكنهم الحصول على حجم الملف أثناء fopen اتصل، ولكن هذا لا يمكن أن يعمل على جميع أنواع موارد الملفات، مما يؤدي إلى سلوك غير متناسق وسيكون أبطأ.

هل كانت مفيدة؟

المحلول

لا تعرف PHP ما إذا كانت موجودة في نهاية الملف حتى تحاول القراءة منه.جرب هذا المثال البسيط:

<?php 
$fp = fopen("/dev/null","rb"); 
while (!feof($fp)) { 
    $data = fread($fp, 1);
    echo "read " . strlen($data) . " bytes";  
} 
fclose($fp); 
?>

سوف تحصل على قراءة سطر واحد read 0 bytes.تم إرجاع الدالة feof()‎ صحيحًا على الرغم من أنك كنت في نهاية الملف من الناحية الفنية.عادة لا يسبب هذا مشكلة لأن fread($fp, 1) لا يُرجع أي بيانات، وأيًا كانت المعالجة التي تجريها والتي لا تعالج أي بيانات بشكل جيد.إذا كنت تريد حقًا معرفة ما إذا كنت في نهاية الملف، فيجب عليك القراءة أولاً.

نصائح أخرى

قد يكون هذا سؤالًا أكثر منه إجابة، ولكن لماذا لا نستخدمه file_get_contents()؟في تجربتي، إذا كنت تقرأ ملفًا أو دفقًا، فإن هذه الوظيفة تقوم بالعمل القذر نيابةً عنك (بافتراض أنك تريد قراءة المورد بالكامل إلى سلسلة، أو معرفة/يمكنك حساب الحد والإزاحة).تعمل الوظيفة الشقيقة file_put_contents() بشكل جيد، في الاتجاه المعاكس.

على سبيل المثال، هنا مثال:

$expected_content = "Hello Stack Overflow!"
$real_content = file_get_contents("/path/to/file.txt");
if ($expected_content != $real_content){
   file_put_contents("/path/to/file.txt", $real_content);
}

أو تيار:

$expected_content = "Hello Stack Overflow!"
$real_content = file_get_contents("http://host.domain.com/file.txt");
if ($expected_content != $real_content){
   $options = array('ftp' => array('overwrite' => true));
   $stream = stream_context_create($options); 
   file_put_contents("ftp://user:pass@host.domain.com/file.txt", $real_content, 0, $stream);
}

إذن لا داعي للقلق بشأن EOF أو أي شيء آخر، فهو يفعل ذلك نيابةً عنك (يصبح وضع بروتوكول نقل الملفات مشبوهًا بعض الشيء، لكن لا بأس بذلك).وبطبيعة الحال، هذا لن ينجح في جميع الحالات...

هل هناك شيء أفتقده في السؤال الأصلي يجعل هذا النهج غير ممكن؟

تأكيدك على عدم الاتصال feof قبل fread غير صحيح - وبالتالي فإن السؤال غير صحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top