7

I sense that I am almost there. Here is a .txt file, which is about 60 Kbytes and full of German words. Every word is on a new line.

I want to iterate through it with this code:

<?php

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

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

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

?>

When I execute this code, I get: Resourceid#2 The word resource is not in the .txt, I do not know where it comes from.

How can I manage to show up all words in the txt?

0

5 Answers 5

14

No need for fopen just use 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;
}
1
  • 3
    If the filesize is really big (which is not this case), it proposes a great load on the server. fgets is better in that case
    – Vultour
    Commented Sep 30, 2012 at 21:34
10

fopen() just opens the file, it doesn't read it -- In your code, $f contains a file handle, not the file contents. This is where the word "Resource" comes from; it's PHP's internal name for the file handle.

One answer would be to replace fopen() with file_get_contents(). This opens and reads the file in one action. This would solve the problem, but if the file is big, you probably don't want to read the whole thing into memory in one go.

So I would suggest instead using SplFileObject(). The code would look like this:

<?php
$file = "GermanWords.txt";
$parts = new SplFileObject($file);
foreach ($parts as $line) {
    echo $line;
}
?>

It only reads into memory one line at at time, so you don't have to worry about the size of the file.

Hope that helps.

See the PHP manual for more info: http://php.net/manual/en/splfileobject.construct.php

1

$f, the result of fopen is a resource, not the contents of the file. If you just want an array of the lines contained in the file, you can use file:

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

Alternatively, if you want to stick with fopen you can use fread to read the content:

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

The SplFileObject provides a way to do that :

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

And if you prefer the foreach loop, you can create a generator function for that :

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

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

Reading the entire content of the file (with file_get_contents) before treating it can be memory consuming.

If you want to treat a file line by line, this class might help you.

It implements an Iterator (see phpdoc about it), that can be walked through in a foreach loop. Only the last line read is stored in memory.

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 );
}    

Usage :

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

foreach ($iterator as $line) {
    echo $line;// or do whatever you want with line
}
2
  • Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you’ve made.
    – NOhs
    Commented May 4, 2018 at 10:53
  • I edited the answer to explain it. However, it should be noted that using the existing SplFileObject can be shorter (see the answer I posted) Commented May 17, 2018 at 9:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.