How to fix infinite loop while reading a file and populating an array using fopen?

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

  •  03-10-2022
  •  | 
  •  

Question

I want to read a file and populate an empty array.

Here is my code:

$savedList = array();

readFile1($savedList, "test.txt");

function readFile1($array, $filename){

    $handle = fopen($filename, "r");
    $numElements = count($array);

    while (!feof($handle)) {
        foreach ($array as $x){
            $array[$x] = fgets($handle);
        }   
    }

    fclose($handle);        
}

With the above code, I'm getting the following error:

Fatal error: Maximum execution time of 30 seconds exceeded

How can I fix it?

Was it helpful?

Solution

Why your code doesn't work

The function feof() returns TRUE if the file pointer is at EOF or an error occurs. In all other cases, it returns FALSE. In your code, $array will always be empty at the beginning, and any code inside foreach won't get executed. So the file pointer will always be at the beginning of the file (it will never reach the end), meaning feof($handle) will always return FALSE.

Essentially, your code translates to:

while (TRUE) {
    foreach (array() as $x){
        /*
        code here will never get executed
        */
    }   
}

Looks like an infinite loop, right? Your script times out, and PHP then throws that Fatal error.

What can be done to fix it

For what you want to accomplish, a foreach isn't necessary. You're already using a while loop, so you don't need to loop through $array - it's pointless. Simply declare a counter variable ($x in the code below), and use that to create the array index:

function readFile1($array, $filename){

    $handle = fopen($filename, "r");
    $numElements = count($array);

    $x = 0;
    while (!feof($handle)) {
        $array[$x] = fgets($handle);
        $x++;
    }

    fclose($handle);     
    return $array;   
}

Note that the $x variable above is just for demonstration purposes. If you actually wanted to have 0-based array indices, then you could simply push each line to the array using [] syntax or array_push(). For example:

while (!feof($handle)) {
    $array[] = fgets($handle);
}

Now, call the function and store the returned array and use it however you wish:

$arr = readFile1($savedList, "test.txt");
print_r($arr);

OTHER TIPS

  • You are starting with an empty array $savedList, and passing it into the parameter $array
  • You are setting $numElements to the size of $array, which is zero
  • You are looping based on the condition that you haven't hit the end of the file
  • You are running a foreach over an empty array, so the position in the file is never advanced
  • ...and the loop goes on and on and on...

The problem is that you nest two loops into each other.

The inner loop gets executed exactly zero times, which means fgets can't push the file position towards eof, which is why your outer loop never terminates.

function readFile1($filename){
    $handle = fopen($filename, "r");
    $array = array();
    while (!feof($handle)) {
        $array[] = fgets($handle);
    }
    fclose($handle);
    return $array;
}

Assuming $array is pre-filled... Your foreach ($array as $x){ iterates trough values (it's the same as iterating trough result of array_values()) but you want $x to have value based on key (iterating trough array_keys()) which is supported by foreach by this syntax:

foreach ($array as $x => $value){
    $array[$x] = fgets($handle);
}   
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top