1

I am trying to display the total number in each line of a file that does not contain a path to another file as well as the filename, but if it has a path to another file loop through that file and sum all the number it has and the loop goes on and on as long as there exists a path to a file in the current file.

here is my code

function fileProcessor($value){
    if(file_exists(trim($value))){
        $total = 0;
        $files = file($value, FILE_SKIP_EMPTY_LINES);
        foreach($files as $data) {
            if(!preg_match("/.txt/i", $data)){
                $num = floatval($data);
                $total += $num;
            } else {
                fileProcessor(trim($data));
            }
        }
        echo $value. ' -  ' .($total);
    } else {
        echo 'File does not exist';
    }

    fileProcessor('text_files/first.txt');
}

I have 3 .txt files I'm working with, inside those files I have something like this

first.txt


  • 1
  • 3
  • 3
  • second.txt

second.txt


  • 2
  • 3
  • third.txt

third.txt


  • 1
  • 2

The output I am looking for


  • first.txt - 15
  • second.txt - 8
  • third.txt - 3

I will really appreciate it if someone can point me in the right direction, I don't know if I'm doing it right.

4
  • for starters, you're not returning anything from the function so it doesn't know when to stop executing Commented Jun 1, 2021 at 22:45
  • also, why are you always calling fileProcessor('text_files/first.txt');? is that meant to be kicking off the process? if so that should probably be called outside of the function Commented Jun 1, 2021 at 22:47
  • thanks @pew007 I am calling the function fileProcessor('text_files/first.txt'); to kick off the process Commented Jun 1, 2021 at 23:38
  • also I tried returning $total += $num; and fileProcessor(trim($data)); before posting the question here it didn't work; Commented Jun 1, 2021 at 23:43

2 Answers 2

0

There are two problems with your code:

  • You're not including the directory for the source file in the path to subsidiary files, so those files are never found.
  • You're not returning the total from the function so that higher level invocations can add the total for subsidiary files

Correcting those issues, and renaming the variables to something meaningful gives this code:

function fileProcessor($filename){
    if(file_exists(trim($filename))){
        $total = 0;
        $rows = file($filename, FILE_SKIP_EMPTY_LINES);
        foreach($rows as $data) {
            if(!preg_match("/.txt/i", $data)){
                $num = floatval($data);
                $total += $num;
            }else {
                $total += fileProcessor(dirname($filename)."/".trim($data));
            }
        }
        echo $filename. ' -  ' .($total)."<br>\n";
    }else{
        echo "File does not exist<br>\n";
    }
    return $total;
}

fileProcessor('text_files/first.txt');

Output:

text_files/third.txt - 3
text_files/second.txt - 8
text_files/first.txt - 15

This lists the files in the order in which the totals are finally accumulated, so the lowest levels appear first.

[Edit] I spotted a problem with the order of results if two or more filenames appear in a file. Here's a reworked version that deals with that.

To list the files in the order in which they are encountered requires reversing the natural order. In the new version below I've placed the filenames in a $fileList array which is passed down by reference. Each new invocation of the function adds its results to the end of that array. Once processing is complete the array is displayed.

function fileProcessor( &$fileList){
    // Get the last filename in the array
    end($fileList);
    $filename = key($fileList);

    if(file_exists(trim($filename))){
        // Accumulate the values
        $fileList[$filename] = 0;
        $rows = file($filename, FILE_SKIP_EMPTY_LINES);
        foreach($rows as $data) {
            if(!preg_match("/.txt/i", $data)){
                $num = floatval($data);
                $fileList[$filename] += $num;
            }else {
                // Recursive call. Add the next filename to the array
                $fileList[dirname($filename)."/".trim($data)]=0;
                $fileList[$filename] += fileProcessor($fileList);
            }
        }
    } else {
        $fileList[$filename]=  "File does not exist: $filename";
    }

    // return the total for the file to add to the accumulator for the file above.
    return  $fileList[$filename];
}


// Place the initial file in the array
$results = ['text_files/first.txt' => 0];

// run the function
fileProcessor($results);

// display the results
foreach($results as $filename=>$total) {
    echo $filename.' - '.$total."<br>\n";
}

Output:

text_files/first.txt - 15
text_files/second.txt - 8
text_files/third.txt - 3
Sign up to request clarification or add additional context in comments.

6 Comments

thanks for your help when I tried the two code sample that you gave but I kept running into another error File does not exist<br> File does not exist<br> text_files/first.txt - 44 when I modified the code to specify the right path the page won't load just like before
Also all my .txt files are located inside the text_files directory
The code works as shown on my development server. It assumes that the initial file can be reached with the path you pass in, and that all subsidiary files are in the same directory as the starting file. If you've modified the code here and now it's not working then something is wrong with your modifications.
this is my modification echo dirname($filename)."/".trim($data); //$total += fileProcessor(dirname($filename)."/".trim($data)); I am only echoing out the directory specified in the fileprocessor function to know if the path is correct and it happened that it's not. its showing text_files/text_files/second.txt text_files/text_files/third.tx but the right path is text_files/second.txt and when i made that correction, the page just keeps loading but won't display anything just like before
Something else is wrong, then. Look in your server error log for possible errors
|
0

You could use the static var:

<?php
function fileProcessor($value) {
    static $results = [];
    if (file_exists(trim($value))) {
        $results[$value] = 0;
        $files = file($value, FILE_SKIP_EMPTY_LINES);
        foreach($files as $data) {
            if (!preg_match("/.txt/i", $data)) {
                $num = floatval($data);
                $results[$value] += $num;
            } else {
                fileProcessor(trim($data));
            }
        }
    } else {
        echo 'File does not exist';
    }
    reset($results);
    if (key($results) != $value) {
        return;
    }
    foreach($results as $key => $value) {
        echo $key. ' -  ' .$value."\n";
    }
}

fileProcessor('text_files/first.txt');

Output:

text_files/first.txt -  7
text_files/second.txt -  5
text_files/third.txt -  3

1 Comment

thanks, Artem but the result is still the same the page won't load, it will just keep loading but won't display anything after a while I will get maximum execution time error. if I run the code in the terminal it won't even load at all

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.