7

I have a PHP routine that reads a .csv file that has been uploaded to my site.

The number of fields in the file may be different from upload to upload.

I want to be able to establish the size of the .csv file (the number of fields) and then store its contents in an array.

This is what I have so far:

//get the csv file 
$file = $_FILES[csv1][tmp_name]; 
$handle = fopen($file,"r"); 

//loop through the csv file and insert into array
$dataline = fgetcsv($handle,1000,",","'");
$fieldnum = count($dataline);

$recordloop = 0;

while ($dataline) 
{ 

    for ($fieldloop=0; $fieldloop <$fieldnum; $fieldloop++)
    {
        //this is the bit that is wrong
        $dataarray[]=array($dataline[$fieldloop]);
    }

    $data = fgetcsv($handle,1000,",","'");
    $recordloop++;
}

If for example, there are 30 fields and 200 records I am trying to get the array to be of the structure $dataarray[200][30].

How do I get the data into the array of this structure?

Example .csv:

Row 1 will be field headings
Name, Gender, Ethnicity, DOB, etc .... the number of fields is not fixed - it could be from 30 to 40 fields in this row

Rows 2 onwards will be the records
John, M, British, 10/04/49, etc
Simon, M, British, 04/03/65, etc

ANSWER - did just what I wanted

$file = $_FILES[csv1][tmp_name]; 
$handle = fopen($file,"r"); 

$matrix = array();
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) 
{
$matrix[] = $row;
}
2

3 Answers 3

20

You already have this kind of implementation in PHP:

$csv = array_map('str_getcsv', file('someCSVfile.csv'));

Explanation:

  • str_getcsv() - Parse a CSV string into an array.
  • file() - Reads entire file into an array.
  • array_map(Function, Array)- Returns an array containing all the elements of the array after applying the callback function to each one.

Example output:

//CSV
NAME,CLASS,ROOM
Sally,2018,312
Belinda,2017,148

//OUTPUT:
Array(
       [0] => Array([0] => NAME,    [1] => CLASS, [2] => ROOM), 
       [1] => Array([0] => Sally,   [1] => 2018,  [2] => 312),
       [2] => Array([0] => Belinda, [1] => 2017,  [2] => 148)
)

Associative keys

Two quick functions to parse with associative keys - both based on the array_map method:

METHOD 1: running twice

function assoc_getcsv($csv_path) {
    $r = array_map('str_getcsv', file($csv_path));
    foreach( $r as $k => $d ) { $r[$k] = array_combine($r[0], $r[$k]); }
    return array_values(array_slice($r,1));
}  

METHOD 2: running once

function assoc_getcsv($csv_path) {
    $f = array();
    function parse_csv_assoc($str,&$f){ 
        if (empty($f)) { $f = str_getcsv($str); }
        return array_combine($f, str_getcsv($str));         
    }
    return array_values(array_slice(array_map('parse_csv_assoc', file($csv_path), $f),1));
} 

Example output:

//CSV
NAME,CLASS,ROOM
Sally,2018,312
Belinda,2017,148

//OUTPUT:
Array(
       [0] => Array([NAME] => Sally,   [CLASS] => 2018,  [ROOM] => 312),
       [1] => Array([NAME] => Belinda, [CLASS] => 2017,  [ROOM] => 148)
)
Sign up to request clarification or add additional context in comments.

4 Comments

That's an interestingly short way of getting the job done. Just out of curiosity - have you compared the speed of this and working with SplFileObject and an Iterator?
No -> I'm using this function for month and parsing 11K CSV in ~1-2secs
This definitely is twice as fast as using an SplFileObject. Here's my test.
@tftd great test! are you up to test the two other methods too?
4

this function will read a CSV and generate a multi-dimensional array

function fromCSVFile( $file) {
    // open the CVS file
    $handle = @fopen( $file, "r");
    if ( !$handle ) {
        throw new \Exception( "Couldn't open $file!" );
    }

    $result = [];

    // read the first line
    $first = strtolower( fgets( $handle, 4096 ) );
    // get the keys
    $keys = str_getcsv( $first );

    // read until the end of file
    while ( ($buffer = fgets( $handle, 4096 )) !== false ) {

        // read the next entry
        $array = str_getcsv ( $buffer );
        if ( empty( $array ) ) continue;

        $row = [];
        $i=0;

        // replace numeric indexes with keys for each entry
        foreach ( $keys as $key ) {
            $row[ $key ] = $array[ $i ];
            $i++;
        }

        // add relational array to final result
        $result[] = $row;
    }

    fclose( $handle );
    return $result;
}

So if your .CSV file looks like this:

Name,Gender,Ethnicity,DOB
John,M,British,10/04/49
Simon,M,British,04/03/65

You will get this:

(
    [0] => Array
        (
            [name] => John
            [gender] => M
            [ethnicity] => British
            [dob] => 10/04/49
        )

    [1] => Array
        (
            [name] => Simon
            [gender] => M
            [ethnicity] => British
            [dob] => 04/03/65
        )

)

1 Comment

Thanks, and that is great but I don't actually want the first row to become the key. I want them to remain in the first row of the array.
4

1.csv:

Name,Gender,Ethnicity,DOB
John,M,British,10/04/49
Simon,M,British,04/03/65

Use file() to read the csv file into an array, then iterate through this array and get all the fields into an array element with explode() and make your new $array

<?php

$file = '1.csv';
$content = file($file);

$array = array();

for($i = 1; $i < count($content); $i++) {
    $line = explode(',', $content[$i]);
    for($j = 0; $j < count($line); $j++) {
        $array[$i][$j + 1] = $line[$j];
    }   
}   

print_r($array);

?>

Output:

Array
(
    [1] => Array
        (
            [1] => John
            [2] => M
            [3] => British
            [4] => 10/04/49

        )

    [2] => Array
        (
            [1] => Simon
            [2] => M
            [3] => British
            [4] => 04/03/65

        )

)

If you want get record:2 and field:4 you can do this:

echo $array[2][4];

Output:

04/03/65

2 Comments

@RichardGriffiths do you got some advance?
? - I have found the answer. I have edited the question to show the answer. Thanks for your help.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.