PHP中读取和迭代.txt文件

7

我感觉我快做完了。

这是一个大约60K字节且充满德语单词的 .txt 文档,每个单词占据一行。

我想使用以下代码遍历它:

<?php

    $file = "GermanWords.txt";
    $f = fopen($file,"r");

    $parts = explode("\n", $f);

    foreach ($parts as &$v) 
    {
        echo $v;
    }

?>

当我执行这段代码时,我得到了:Resourceid#2。 单词“resource”不在.txt文件中,我不知道它从哪里来的。
我该如何才能显示txt中的所有单词?
5个回答

14

不需要使用fopen,直接使用file_get_contents

$file = "GermanWords.txt";
$contents = file_get_contents($file);
$lines = explode("\n", $contents); // this is your array of words

foreach($lines as $word) {
    echo $word;
}

3
如果文件大小真的很大(这并不是现在的情况),它会对服务器造成很大的负担。在这种情况下,使用 fgets 更好。 - Vultour

10

fopen()函数只是打开文件,不会读取文件 -- 在您的代码中,$f 包含的是文件句柄,而不是文件内容。这也是“资源”一词来自于何处; 它是 PHP 对文件句柄的内部名称。

一个解决方法是用 file_get_contents() 替换 fopen()。 这会在一次操作中打开并读取文件。 这将解决问题,但如果文件很大,您可能不希望一次性将整个文件读入内存。

因此,我建议改用 SplFileObject()。 代码应如下所示:

<?php
$file = "GermanWords.txt";
$parts = new SplFileObject($file);
foreach ($parts as $line) {
    echo $line;
}
?>
它只会一次读取一行到内存中,所以您不必担心文件大小。
希望这有帮助。
查看PHP手册获取更多信息:http://php.net/manual/en/splfileobject.construct.php

1

SplFileObject提供了一种实现此操作的方法

$file = new SplFileObject("file.txt");
while (!$file->eof()) {
    echo $file->fgets();
}

如果您更喜欢使用 foreach 循环,您可以为此创建一个生成器函数

function lines($filename) {
    $file = new SplFileObject($filename);
    while (!$file->eof()) {
        yield $file->fgets();
    }
}

foreach (lines('German.txt') as $line) {
    echo $line;
}

1

$ffopen 的结果是一个资源,而不是文件的内容。如果你只想要包含在文件中的行的数组,可以使用 file

$parts = file('GermanWords.txt');
foreach($parts as $v){
    echo $v;
}

或者,如果您想坚持使用fopen,您可以使用fread来读取内容:

$f = fopen('GermanWords.txt', 'r');
// read the entire file into $contents
$contents = fread($f, filesize('GermanWords.txt'));
fclose($handle);
$parts = explode("\n", $contents);

0

在处理文件之前使用file_get_contents读取整个文件内容可能会消耗大量内存。

如果您想逐行处理文件,则此类可能会对您有所帮助。

它实现了一个迭代器(请参见phpdoc about it),可以在foreach循环中遍历。只有最后一行读取的内容存储在内存中。

class TxtFileIterator implements \Iterator{

protected $fileHandler;
protected $key;
protected $current;
protected $fileName;

function __construct($fileName){
    $this->fileHandler = fopen($fileName, "r") or die("Unable to open file!");        

    $this->fileName = $fileName;
    $this->key = 0;
}

function __destruct(){
    fclose( $this->fileHandler );
}

//Iterator interface
public function current (){       
    return $this->current;
}

public function key (){
    return $this->key;
}

public function next (){
    if ( $this->valid() ){
        $this->current = fgets( $this->fileHandler );
        $this->key++;
    }
}

public function rewind (){
    $this->__destruct();
    $this->__construct( $this->fileName );
}

public function valid (){
    return !feof( $this->fileHandler );
}    

用法:

$iterator = new TxtFileIterator("German.txt");

foreach ($iterator as $line) {
    echo $line;// or do whatever you want with line
}

谢谢您提供这段代码片段,它可能会提供一些有限的、即时的帮助。一个适当的解释将极大地提高它的长期价值,因为它可以展示为什么这是一个好的问题解决方案,并且使其对未来读者具有其他相似问题更有用。请编辑您的答案添加一些解释,包括您所做的假设。 - NOhs
我编辑了答案来解释它。但是需要注意的是,使用现有的SplFileObject可能会更短(请参见我发布的答案)。 - Pierre-Olivier Vares

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接