まず、 Feof()の基本的な使用法を理解しましょう。この関数のプロトタイプは次のとおりです。
<span><span><span class="hljs-keyword">bool</span></span><span> </span><span><span class="hljs-title function_ invoke__">feof</span></span><span>(resource </span><span><span class="hljs-variable">$handle</span></span><span>);
</span></span>
ファイルリソース(通常はFOPEN()関数によって開かれるファイルハンドル)をパラメーターとして受け入れ、ファイルポインターがファイルの最後に到達したときにtrueを返し、それ以外の場合はfalseを返します。通常、ファイルを読み取るときは、 Fread()やfgets()などの関数と組み合わせてファイルを使用して、ファイルが読み取られているかどうかを判断します。
バイナリファイルとテキストファイルの最大の違いは、ストレージ形式です。バイナリファイルの各バイトは、データの異なる単位を表す場合があり、特定のNewline文字( \ nや\ r \ nなど)によって必ずしも分離されているわけではありません。したがって、バイナリファイルを読み取るときは、誤った読み取りおよび書き込みの動作を避けるために特別な注意を払う必要があります。
テキストファイルでは、 Feof()は通常、最後の文字を読んだ後にtrueを返します。これは、ファイル内のNewlinesがプログラムによって簡単に認識され、終了するためです。バイナリファイルでは、ファイルには明らかな「エンド文字」または「ラインエンド文字」がないため、 Feof()は、ファイルの読み取りを完了していない場合に事前にTrueを返すことがあり、データ損失になります。
バイナリファイルを使用する場合、 Feof()で次の一般的な問題が発生する可能性があります。
バイナリデータを読み取るとき、 Feof()がtrueを返す場合は、ファイルが完全に読み取られていることを意味しない場合があります。 feof()がtrueを返したとしても、ファイルが完全に読み取られていないことがある場合があります。これは、 Feof()がファイルの最後の条件がファイルのポインター位置に基づいていると判断したためですが、読んだすべてのバイトが完全に取得されたことを保証するものではありません。
バイナリファイルでは、読み取り中に特定のデータ構造(固定長レコードなど)がある場合、読み取り中にファイルポインターの位置を厳密に制御する必要があります。 feof()に頼ってループの読み取り中に終了するかどうかを判断する場合、場合によってはデータ構造の半分を読み取ることができるかもしれません。
たとえば、複数の固定長レコードを含むバイナリファイルを読み取る場合、 Feof()は、最後のレコードの一部が読み取られたときにtrueを返す場合がありますが、実際にはすべてのデータを完全に読み取っていません。
Fread()を使用してファイルを読み取る場合は、特に注意してください。 fread()は、ファイルの最後まで読み取られたときに読み取られた実際のバイト数を返します。 feof()がループ終了のフラグとしてのみ使用される場合、データが完全に読み取られていないときにfeof()がtrueを返す可能性があります。この時点で、プログラムは読み取り操作を終了し、データの読み取り値が欠落します。
これを回避するには、通常、 feof()に依存するのではなく、データを読み取るときに読み取る実際のバイト数を判断する必要があります。例えば:
<span><span><span class="hljs-variable">$handle</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fopen</span></span><span>(</span><span><span class="hljs-string">'binary_file.dat'</span></span><span>, </span><span><span class="hljs-string">'rb'</span></span><span>);
</span><span><span class="hljs-keyword">while</span></span><span> (!</span><span><span class="hljs-title function_ invoke__">feof</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>)) {
</span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fread</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>, </span><span><span class="hljs-number">1024</span></span><span>); </span><span><span class="hljs-comment">// それぞれが読むと仮定します1024バイト</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">strlen</span></span><span>(</span><span><span class="hljs-variable">$data</span></span><span>) < </span><span><span class="hljs-number">1024</span></span><span>) {
</span><span><span class="hljs-comment">// データの最後の部分を処理します</span></span><span>
</span><span><span class="hljs-keyword">break</span></span><span>;
}
</span><span><span class="hljs-comment">// 読み取りデータを処理します</span></span><span>
}
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>);
</span></span>
このようにして、各データを読み取った後、実際のバイトの読み取り数をチェックすることにより、ファイルの終了が誤解されないようになります。
Feof()がバイナリファイルを処理する際に引き起こす可能性のある問題を解決するには、次の提案を次に示します。
バイナリファイルを読み取るときは、 Fread()の返品値の長さを使用して、ファイルが読み取られているかどうかを判断できます。 FREAD()によって返されるデータの長さが予想されるバイト数よりも少ない場合、ファイルの終了に到達したことを意味します。これにより、 Feof()への依存を避けることができます。
ファイルコンテンツが完全に読み取られていることを確認する必要がある場合は、 ftell()関数を組み合わせて現在のファイルポインターの場所を確認できます。ポインターがファイルの終了に到達した場合、ファイルの読み取りが完了していることを確認できます。
<span><span><span class="hljs-variable">$handle</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fopen</span></span><span>(</span><span><span class="hljs-string">'binary_file.dat'</span></span><span>, </span><span><span class="hljs-string">'rb'</span></span><span>);
</span><span><span class="hljs-keyword">while</span></span><span> (!</span><span><span class="hljs-title function_ invoke__">feof</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>)) {
</span><span><span class="hljs-variable">$pos</span></span><span> = </span><span><span class="hljs-title function_ invoke__">ftell</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>);
</span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fread</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>, </span><span><span class="hljs-number">1024</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">strlen</span></span><span>(</span><span><span class="hljs-variable">$data</span></span><span>) < </span><span><span class="hljs-number">1024</span></span><span>) {
</span><span><span class="hljs-keyword">break</span></span><span>;
}
</span><span><span class="hljs-comment">// データの処理</span></span><span>
}
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$handle</span></span><span>);
</span></span>
バイナリファイルに特定の構造(固定長レコードなど)がある場合、 Feof()に依存して読み取りプロセスを終了するのではなく、ファイル形式に基づいて時間ごとに読み取られるバイト数を指定する必要があります。事前にファイル形式を理解することにより、読み取りプロセスをより正確に制御し、誤読や脱落を避けることができます。
PHPでバイナリファイルを処理する場合、いくつかの特別な予防策があります。バイナリファイルには明らかなセパレータがないため、 Feof()に依存してファイルが読み取られているかどうかを判断することは信頼できるプラクティスではありません。ファイルの完全な読み取りを確保するには、 FREAD() 、 FTELL()のファイルポインター位置の返品値の長さを使用するか、ファイル構造に基づいてより正確なコントロールを実行することをお勧めします。これらの方法は、Feof()の不完全性によるデータの損失を回避するのに役立ちます。