PHP - strtok(), associative array relationship

553 views Asked by At

I'm pretty familiar with the Strtok() function in PHP, and I have had no problem getting the function to work properly for strings in the past. However, I currently have to read a .csv text file (which I've done successfully) where each line is made of 6 fields like so: last name, first name, address, city, district, postal code\r\n <--carriage return and linefeed at the end

I have to use Strok() to split these by the delimiters and token the words as fields (i.e. last, first, address, etc.). I plan to use an associative array using the last name as the primary key so that I can plug the data into an HTML Table, which is created and working. My issue right now is splitting the file correctly, as it has about 200 lines made of those 6 fields, and storing the strings as fields properly for an array, so the data structure is where I'm having some issues. Here's what I have so far:

    $inputFile = fopen("input.csv","r");
    $delimiters = ",";
    $token = strtok($inputFile, $delimiters);
    $n=1;

    while ($token){
      echo "Token $n: $token <br>";
      $token = strtok($delimiters);
      $n++;
    }

Obviously, the table is created below it but since I haven't done the data structure quite yet, I don't have the fields for it. I think my token loop may be incorrect for this issue, but I pulled some from an earlier example in my book and an exercise I did where my token process worked but the file structure was different. Thanks for any direction or help on this.

2

There are 2 answers

2
trincot On BEST ANSWER

There are CSV functions in PHP, like fgetcsv, so it really is the wrong approach to reinvent the wheel.

Note that in your code you don't actually read the content of the file, as you only get a file pointer.

If you really need to do this with strtok, and your CSV is simple, in the sense that it does not have quoted strings, which could have embedded delimiter characters, you could use:

  • file_get_contents() to read the file content in one string. Of course, file() would make it easier for you, as it would already split lines. But I assume that if CSV functions are not allowable for you, then this will neither.

  • strtok for getting the fields, but at the end of the loop, not at the start, since the initial call with the double arguments already retrieves the first value before the loop.

Code:

$input = file_get_contents("input.csv");
$delimiters = ",\n\r";

$token = strtok($input, $delimiters);
$result = [];
$row = [];
while ($token){
    echo "Token $token <br>";
    $row[] = $token;
    if (count($row) == 6) { // write record
        $result[] = $row;
        $row = [];
    }
    $token = str_replace('\r', '', strtok($delimiters));
}

print_r($result);

Note that this does not create an associative array. If you need that, then use this code:

 $columns = ['last', 'first', 'address1', 'address2', 'address3', 'zip'];

and then in your loop, replace $row[] = $token by:

        $row[$columns[count($row)]] = $token;

You can see that version run on eval.in. The output for the data you provided in comments is:

Array (
    [0] => Array (
        [last] => SELBY
        [first] => AARON
        [address1] => 1519 Santiago de los Caballeros Loop
        [address2] => Mwene-Ditu
        [address3] => East Kasai
        [zip] => 22025
    )
    [1] => Array (
        [last] => GOOCH
        [first] => ADAM
        [address1] => 230 Urawa Drive
        [address2] => Adoni
        [address3] => Andhra Pradesh
        [zip] => 2738
    )
)

Again, this is not advisable. You should use fgetcsv. That also deals better with strings that could have commas, double quotes or even newlines in them.

3
AbraCadaver On

Well, I was going to skip this question because fgetcsv(), but I was bored:

$lines = file($inputFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$delimiters = ",";

foreach($lines as $line) {
    $values = array(strtok($line, $delimiters));
    while($token = strtok($delimiters)){
        $values[] = $token;
    }
    $result[] = $values;
}
  • Read the file lines into an array
  • Loop to get each line and put the first token of the line into a values array
  • Loop the line and get all tokens and add to values array
  • Add values array to result array

I added an array_combine() because you said something about an associative array. You can use something like this if needed:

    $result[] = array_combine(array('last name',
                                    'first name',
                                    'address',
                                    'city',
                                    'district',
                                    'postal code'), $values);

If you wanted last name to be the key for each result line, which is not advisable as keys are unique and I don't think you can guarantee last names being unique:

    $result[$values[0]] = $values;
    //or to remove it from the array but use as the key
    $result[array_unshift($values)] = $values;