$파일->eof()항상 false 를 반환할 때 사용하여 PHP SplFileObject 에'r'모드
-
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(...
다)및 그것을 대체 this:
$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
클래스를 작성합니다.를 호출하지 않고 next()
고 current()
메서드를 사용하는 기본(0
)플래그—반복기 절대 앞으로 이동합니다.
이 iterator_count()
함수 호출하지 않 current()
;확인 valid()
와 통화 next()
니다.귀하의 맞춤형 루프를 만화 중 하나 또는 기타의 current()
고 next()
.
이 것으로 간주되어야 버그(에서 여 PHP 자체가 실패하거나 설명서)및 다음과 같은 코드 야 (하지 않)예상대로 작동합니다.나는 당신을 초대 보고서 이 비행.
// NOTE: This currently runs in an infinite loop!
$file = new SplFileObject(__FILE__);
var_dump(iterator_count($file));
해결 방법
한 빠른 회피 움직이는 물건을 얻을 수을 설정하는 것입니다 READ_AHEAD
깃발에서 객체입니다.이의 원인이됩니다 next()
메서드를 읽을 다음 사용 가능한 라인입니다.
$file->setFlags(SplFileObject::READ_AHEAD);
는 경우,어떤 이유로,당신은 당신을 원하지 않는 미리 읽기 행동한 다음 호출해야 합니다 모두 next()
고 current()
자신입니다.
다시 원래의 문제는 두 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 "바"
총 라인 : 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 : "바"는 끝입니까?아니오
라인 : 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();
}
.
그래서 :
$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();
.