在PHP manual,在SplFileObject
有兩種方法似乎很相似:fgets和當前有什麼區別?
$file->fgets()
從文件一行。
$file->current()
檢索該文件的當前行。
對文檔的程序fgets
,更接近current()
:
從文件指針線。
但是沒有關於其中一個別名的註釋。兩者都沒有參數。這些有何區別?
在PHP manual,在SplFileObject
有兩種方法似乎很相似:fgets和當前有什麼區別?
$file->fgets()
從文件一行。
$file->current()
檢索該文件的當前行。
對文檔的程序fgets
,更接近current()
:
從文件指針線。
但是沒有關於其中一個別名的註釋。兩者都沒有參數。這些有何區別?
物質的真正區別是,例如我們有這個文件
foo
bar
以下功能將打印foo bar
$file = new \SplFileObject("test.txt");
while (!$file->eof()) {
echo $file->fgets();
}
但是這個功能將打印foo
不斷
$file = new \SplFileObject("test.txt");
while (!$file->eof()) {
echo $file->current();
}
因爲從fgets
開始開始,讀出下一行是第一行,然後它讀取下一行,這是秒行,並停止,因爲它發現文件的結尾,但current
總是讀取當前行,從來就沒有到下一行,所以它永遠不會打破循環,你需要使用next
函數讀取下一行,所以第一個代碼是等效採用:
$file = new \SplFileObject("test.txt");
while (!$file->eof()) {
echo $file->current();
$file->next();
}
實施中有一些差異。好像fgets
更短,它只做什麼說讀取線從文件
https://github.com/php/php-src/blob/4d9a1883aa764e502990488d2e8b9c978be6fbd2/ext/spl/spl_directory.c
/* {{{ proto string SplFileObject::current()
Return current line from file */
SPL_METHOD(SplFileObject, current)
{
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
}
if(!intern->u.file.stream) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
return;
}
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
spl_filesystem_file_read_line(getThis(), intern, 1);
}
if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
} else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
RETURN_ZVAL(&intern->u.file.current_zval, 1, 0);
}
RETURN_FALSE;
} /* }}} */
VS
/* {{{ proto string SplFileObject::fgets()
Rturn next line from file */
SPL_METHOD(SplFileObject, fgets)
{
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
}
if(!intern->u.file.stream) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
return;
}
if (spl_filesystem_file_read(intern, 0) == FAILURE) {
RETURN_FALSE;
}
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
} /* }}} */
編輯: 所以不同之處在於回報。 current
(如果設置了某些標誌)可能會返回RETURN_ZVAL(這個例子的php數組)或者OR。 fgets
返回字符串或FALSE。另外if (spl_filesystem_file_read(intern, 0) == FAILURE) {
如果我們只是想從文件中讀取一行而不做任何其他工作,那麼它比其他任何東西都快。
請解釋一下代碼,不只是複製粘貼 – Almis
我看到'RETURN_STRINGL(intern-> u.file.current_line,intern-> u.file.current_line_len);'兩個。這是什麼'如果{ spl_filesystem_file_read_line(獲得OS 3.0(),實習生,1)(intern-> u.file.current_line && Z_ISUNDEF(intern-> u.file.current_zval)!); }'做? – Josiah
謝謝。我認爲編輯回答了我的問題。我會等幾分鐘,看看有沒有更多的信息。你能想到一個情況,你會選擇'current()'而不是其中的一個?這似乎有點毫無意義。 – Josiah
一個區別是current
可以作爲fgetcsv
或fgets
depending on whether the SplFileObject::READ_CSV
flag is set。根據該標誌,底層實現幾乎相同(不移動指針,查看其他答案)。
這意味着current
可以返回一個字符串或一個數組,取決於標誌的存在。
大概這是爲代碼可移植性完成的,儘管看起來它會比完成相同工作的代碼多於fgetcsv
,並且由於額外的邏輯調用(請參閱Axalix的答案)可能性能稍差。
如果你downvote,請讓我知道爲什麼這樣我就可以改善這個問題。謝謝! – Josiah
我不知道人們爲什麼低估它,但我也想知道這些方法之間的根本區別。他們看起來模棱兩可,差別很小。 – Axalix
似乎唯一的區別是當前READ_CSV的事情,但你可能也看到了這一點。這是一個很好的問題。 – rjdown