$ file-> eof() 'R'モードでPHPのSplFileObjectを使用する場合は常にfalseを返します。

StackOverflow https://stackoverflow.com//questions/11706174

  •  13-12-2019
  •  | 
  •  

質問

なぜ私のPHPスクリプトがぶら下がっているのですか?

$path = tempnam(sys_get_temp_dir(), '').'.txt';
$fileInfo = new \SplFileInfo($path);
$fileObject = $fileInfo->openFile('a');
$fileObject->fwrite("test line\n");
$fileObject2 = $fileInfo->openFile('r');
var_dump(file_exists($path));          // bool(true)
var_dump(file_get_contents($path));    // string(10) "test line
                                       // "
var_dump(iterator_count($fileObject2)); // Hangs on this
.

最後の行(iterator_count(...)を削除してこれに置き換えた場合:

$i = 0;
$fileObject2->rewind();
while (!$fileObject2->eof()) {
    var_dump($fileObject2->eof());
    var_dump($i++);
    $fileObject2->next();
}

// Output:
// bool(false)
// int(0)
// bool(false)
// int(1)
// bool(false)
// int(2)
// bool(false)
// int(3)
// bool(false)
// int(4)
// ...
.

$fileObject->eof()は常にfalseを返しますので、無限ループが表示されます。

なぜこれらのことが起こっているのですか?ラインカウントを受ける必要があります。

役に立ちましたか?

解決

なぜこれらのことが起こっているのですか?

SplFileObjectクラスが書き込まれるように、PRECULITIERを経験しています。 next() および current()メソッドを呼び出さずに - デフォルト(0)フラグを使用して、イテレータは前方に移動しません。

iterator_count()関数はcurrent()を呼び出すことはありません。 valid()をチェックし、next()を呼び出します。あなたのオーダーメイドのループは、current()next()のうちの1つまたは他のものだけを呼び出します。

これは、(PHP自体のどちらであろうとしているか文書の障害であるか)と見なされ、予想通りに作業するべきである。 に招待しますこの不正behavior

// NOTE: This currently runs in an infinite loop!
$file = new SplFileObject(__FILE__);
var_dump(iterator_count($file));
.

回避策

物事を移動するための1つのクイックサイドステープは、オブジェクトにREAD_AHEADフラグを設定することです。これにより、next()メソッドは次の利用可能な行を読み取ります。

$file->setFlags(SplFileObject::READ_AHEAD);
.

何らかの理由で、の読み取りの振る舞いをしたくない場合は、next()current()の両方を自分で呼び出す必要があります。

2つのsplfileObjectsの元の問題に戻る

予想どおりに機能し、ファイルを追加してそのラインカウントを読むことができます。

<?php
$info = new SplFileInfo(__FILE__);
$write = $info->openFile('a');
$write->fwrite("// new line\n");
$read = $info->openFile('r');
$read->setFlags(SplFileObject::READ_AHEAD);
var_dump(iterator_count($read));
.

他のヒント

編集01

あなたがファイル内の行数:

<?php

$path = tempnam(sys_get_temp_dir(), '').'.txt';

$fileInfo = new SplFileInfo($path);
$fileObject = $fileInfo->openFile('a+');

$fileObject->fwrite("Foo".PHP_EOL);
$fileObject->fwrite("Bar".PHP_EOL);

echo count(file($path));  // outputs 2

?>
.



編集02

上記のコードですが、ファイルポインタのために無限ループに入ることなく:

<?php

$path = tempnam(sys_get_temp_dir(), '').'.txt';

$fileInfo = new SplFileInfo($path);
$fileObject = $fileInfo->openFile('a+');

$fileObject->fwrite("Foo".PHP_EOL);
$fileObject->fwrite("Bar");

foreach($fileObject as $line_num => $line) {
    echo 'Line: '.$line_num.' "'.$line.'"'."<br/>";
}
echo 'Total Lines:' . $fileObject->key();

?>
.

出力

行:0 "foo"

線:1 "BAR"

総線:2



オリジナルアンサー

適用された論理は少しオフでした。コードを簡略化しました:

<?php

// set path to tmp with random file name
echo $path = tempnam(sys_get_temp_dir(), '').'.txt';
echo "<br/>";

// new object
$fileInfo = new \SplFileInfo($path);

// open to write
$fileObject = $fileInfo->openFile('a');

// write two lines
$fileObject->fwrite("Foo".PHP_EOL);
$fileObject->fwrite("Bar".PHP_EOL);

// open to read
$fileObject2 = $fileInfo->openFile('r');

// output contents
echo "File Exists: " .file_exists($path);
echo "<br/>";
echo "File Contents: " . file_get_contents($path);
echo "<br/>";

// foreach line get line number and line contents 
foreach($fileObject2 as $line_num => $line) {
  echo 'Line: '.$line_num;
  echo ' With: "'.$line.'" is the end? '.($fileObject2->eof()?'yes':'no')."<br>";
}

?>
.

出力:

/tmp/eadkly.txt

ファイルが存在する:1

ファイルの内容:foo bar

行:0: "foo"は終わりですか?いいえ

行:1: "BAR"が終わりですか?いいえ

行:2: ""は終わりですか?はい

PHP 5.3.9では直感的に見えるかもしれませんが、これは:

<?php
$f = new SplFileObject('test.txt', 'r');
while (!$f->eof()) {
    $f->next();
}
.

無限ループであり、終了しないでください。

ファイルの終わりに達すると、次のように終了します。

<?php
$f = new SplFileObject('test.txt', 'r');
while (!$f->eof()) {
    $f->current();
}
.

SO:

$i = 0;
$fileObject2->rewind();
while (!$fileObject2->eof()) {
    var_dump($fileObject2->eof());
    var_dump($i++);
    $fileObject2->next();
}
.

は次のように書き直す必要があります。

$fileObject2->rewind();
while (!$fileObject2->eof()) {
    $fileObject2->current();
}

$i = $fileObject2->key();
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top