5

There are a few ways to read CSV files with PHP. I used to use the explode function to put each line into an array and then explode commas and use trim to remove any quotation marks from around the data. It was messy...

In PHP 5 there's now fgetcsv and *str_getcsv*... I'm guessing this is the best way to go about it these days so I've whipped together some code...

$fp = fopen($csv_file['file_path'], 'r');       
while (($data = fgetcsv($fp, 0, "\r", '"', "\r")) !== FALSE) {
    $num = count($data);
    for ($c=0; $c < $num; $c++) {
        print_r(str_getcsv($data[$c]));
    }
}

It seems to work but is there a more fail safe approach? For example making it work whether line breaks are \n or \r...

Any input you can give would be awesome!

0

2 Answers 2

6

There is a function for reading files in line-wise: file(), which also works on both linebreak types.

And the shortest method to read in the whole CSV file is:

$data = array_map("str_getcsv", file($filename));

Not sure what your $num = count() was about.

Sign up to request clarification or add additional context in comments.

5 Comments

Hi Mario, thanks for the reply! The code you've given me puts each cell into one array instead of each line into its own array. So I now have a massive array with every cell from every line in it. Am I making sense? How do I break each line into its own array?
The above snippet would give you a two-dimensional $data[$line][$row], the commonly assumed table structure. Not quite sure what you'd want instead. -- If you only wanted to look at each line once, then use a foreach instead: foreach (file($fn) as $line) { $data = str_getcsv($line); }
I think maybe there's something wrong with my CSV file... Here's a coy of it bensinclair.co/import.csv... When I use this file with your code it outputs my data like this img192.imageshack.us/img192/2483/screenshot20111006at123b.png
Oh. In this case, I'm wrong. The file() function does not react well to the Mac-style line endings. Manually split up the file using: $file = preg_split('/[\r\n]+/', file_get_contents($filename)) instead. Then use foreach or the array_map/str_getcsv approach.
Legend! So I presume if they import a Windows or any other line break (if any) it will also work? Thanks for your help!
2

This converts the CSV into a nested array. Might be easier for you to deal with:

<?php
    /**
     * 
     */
    function csv_entry_to_array(array $row)
    {
        $column_count = count($row);
        $csv_column_values = array();

        // Loop through the columns of the current CSV entry and store its value
        for ($column_index = 0; $column_index < $column_count; $column_index++)
        {
            // Store the value of the current CSV entry
            $csv_column_values[] = $row[$column_index];
        }

        // Return
        return $csv_column_values;      
    }

    /**
     * @param string    $input_file_name            Filename of input CSV
     * @param boolean   $include_header_in_output   Flag indicating whether the first entry in the CSV is included in the output or not.
     * @param integer   $length                     Must be greater than the longest line (in characters) to be found in the CSV file (allowing for trailing line-end characters).
     *                                              It became optional in PHP 5. Omitting this parameter (or setting it to 0 in PHP 5.0.4 and later) the maximum line length is
     *                                              not limited, which is slightly slower.
     * @param string    $delimeter                  Set the field delimiter (one character only).
     * @param string    $enclosure                  Set the field enclosure character (one character only).
     * @param string    $escape                     Set the escape character (one character only). Defaults as a backslash.
     * $return  array                               Nested indexed array representing the CSV. Empty array on error (e.g. input file missing, input file not a CSV).
     */
    function csv_file_to_array($input_file_name, $include_header_in_output = TRUE, $length = 1000, $delimeter = ',', $enclosure = '"', $escape = '\\')
    {
        // NOTE: this attempts to properly recognize line endings when reading files from Mac; has small performance penalty
        ini_set('auto_detect_line_endings', TRUE);

        $csv_array = array();

        // Warnings are supressed, but that's OK since the code handles such warnings
        if (($handle = @fopen($input_file_name, "r")) !== FALSE)
        {
            $row_counter      = 0;

            // Iterate over the CSV entries
            while (($row = fgetcsv($handle, $length, $delimeter, $enclosure, $escape)) !== FALSE)
            {           
                if ($row_counter === 0 && $include_header_in_output === TRUE)
                {
                    // This is the first row in the CSV and it should be included in the output
                    $csv_array[] = csv_entry_to_array($row);                
                }
                else if ($row_counter > 0)
                {
                    // This is a row in the CSV that needs to be stored in the return array
                    $csv_array[] = csv_entry_to_array($row);
                }

                $row_counter++;
            }

            // Close file handler
            fclose($handle);
        }
        else
        {
            // Input file: some error occured
            return array();
        }

        return $csv_array;
    }

3 Comments

I also mentioned this to Mario above but I think maybe there's something wrong with my CSV file... Here's a coy of it bensinclair.co/import.csv... When I use this file with your code it outputs my data like what happens with marios code above img192.imageshack.us/img192/2483/screenshot20111006at123b.png I've created the CSV file in Microsoft Excel on Mac. Am I doing something wrong or does something need to be adjusted in the code?
I've updated the code. Added ` ini_set('auto_detect_line_endings', TRUE);`. Give it a try.
At first I didn't use your example because I didn't went to tweak the ini settings but your solution ended up being the best especially when it comes to handling csv data correctly :)

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.