Comment créer un tableau à partir d'un fichier CSV en utilisant PHP et la fonction fgetcsv

106

Quelqu'un peut-il gentiment fournir un code pour créer un tableau à partir d'un fichier CSV en utilisant fgetcsv?

J'ai utilisé le code suivant pour créer un tableau à partir d'un simple fichier CSV, mais cela ne fonctionne pas correctement lorsqu'un de mes champs comporte plusieurs virgules, telles que des adresses.

$lines =file('CSV Address.csv');

foreach($lines as $data)
{
list($name[],$address[],$status[])
= explode(',',$data);
}

* De plus, str_getcsv n'est pas pris en charge par mon service d'hébergement.

Le code ci-dessus ne fonctionne pas avec l'exemple de fichier CSV suivant. La première colonne est le nom, la deuxième colonne est l'adresse, la troisième colonne est l'état matrimonial.

Scott L. Aranda,"123 Main Street, Bethesda, Maryland 20816",Single
Todd D. Smith,"987 Elm Street, Alexandria, Virginia 22301",Single
Edward M. Grass,"123 Main Street, Bethesda, Maryland 20816",Married
Aaron G. Frantz,"987 Elm Street, Alexandria, Virginia 22301",Married
Ryan V. Turner,"123 Main Street, Bethesda, Maryland 20816",Single
Thomas
la source
2
Coincé avec PHP 5.2, hein? Je ressens pour vous, je suis dans le même bateau que mon hébergeur.
Adam F
Vous pouvez utiliser cette aide: github.com/rap2hpoutre/csv-to-associative-array
rap-2-h

Réponses:

179

Comme vous l'avez dit dans votre titre, fgetcsv est la voie à suivre. C'est sacrément facile à utiliser.

$file = fopen('myCSVFile.csv', 'r');
while (($line = fgetcsv($file)) !== FALSE) {
  //$line is an array of the csv elements
  print_r($line);
}
fclose($file);

Vous voudrez y mettre plus de vérification des erreurs en cas d' fopen()échec, mais cela fonctionne pour lire un fichier CSV ligne par ligne et analyser la ligne dans un tableau.

Dave DeLong
la source
Merci Dave mais votre exemple ne fournit qu'un tableau avec les trois positions suivantes: $ line [0], $ line [1] et $ line [2]. C'est bien pour la première ligne, mais je dois créer des positions distinctes pour les lignes 2e, 3e, 4e, etc. De cette façon, je peux manipuler les lignes séparément. J'espère que cela a du sens
Thomas
7
@Thomas Si vous avez besoin d'un tableau de noms, d'adresses et de statuts, vous pouvez simplement faire ce que vous faites ci-dessus: list($names[], $addresses[], $statuses[]) = $line;
Dave DeLong
Merci encore Dave! Cela me faisait trébucher.
Thomas
J'ai une question à propos de cette fonction, si l'un des champs CSV contient une nouvelle ligne, analysera-t-il actuellement la ligne comme un enregistrement unique? Ou va-t-il retourner deux enregistrements (mutilés) à la place?
Alix Axel
pourquoi devons-nous fermer à la fin?
kiwi en colère le
55

Je pense que la syntaxe str_getcsv () est beaucoup plus propre, elle ne nécessite pas non plus que le CSV soit stocké dans le système de fichiers.

$csv = str_getcsv(file_get_contents('myCSVFile.csv'));

echo '<pre>';
print_r($csv);
echo '</pre>';

Ou pour une solution ligne par ligne:

$csv = array();
$lines = file('myCSVFile.csv', FILE_IGNORE_NEW_LINES);

foreach ($lines as $key => $value)
{
    $csv[$key] = str_getcsv($value);
}

echo '<pre>';
print_r($csv);
echo '</pre>';

Ou pour une solution ligne par ligne sans str_getcsv ():

$csv = array();
$file = fopen('myCSVFile.csv', 'r');

while (($result = fgetcsv($file)) !== false)
{
    $csv[] = $result;
}

fclose($file);

echo '<pre>';
print_r($csv);
echo '</pre>';
Alix Axel
la source
2
Pour info: str_getcsv () n'est disponible qu'à partir de PHP 5.3.0. Le projet sur lequel je travaille l'a manqué de 1 version DOH! (nous utilisons 5,2,9 atm).
Jim Ford
C'est excellent, sauf si vous avez des restrictions de mémoire. La solution fgetcsv fonctionne avec n'importe quelle configuration matérielle.
Sp4cecat du
4
IL FAUT SE MÉFIER! il y a un bogue avec str_getcsv qui le fait ignorer les fins de ligne: bugs.php.net/bug.php?id=55763&edit=1
RJD22
Notez que vous pouvez faire: while (! Feof ($ fichier)) {$ csv [] = fgetcsv ($ fichier); } au lieu de while (($ result = fgetcsv ($ file))! == false) {$ csv [] = $ result; }
David G
23

J'ai créé une fonction qui convertira une chaîne csv en tableau. La fonction sait comment échapper les caractères spéciaux et fonctionne avec ou sans caractères de clôture.

$dataArray = csvstring_to_array( file_get_contents('Address.csv'));

Je l'ai essayé avec votre échantillon csv et cela fonctionne comme prévu!

function csvstring_to_array($string, $separatorChar = ',', $enclosureChar = '"', $newlineChar = "\n") {
    // @author: Klemen Nagode
    $array = array();
    $size = strlen($string);
    $columnIndex = 0;
    $rowIndex = 0;
    $fieldValue="";
    $isEnclosured = false;
    for($i=0; $i<$size;$i++) {

        $char = $string{$i};
        $addChar = "";

        if($isEnclosured) {
            if($char==$enclosureChar) {

                if($i+1<$size && $string{$i+1}==$enclosureChar){
                    // escaped char
                    $addChar=$char;
                    $i++; // dont check next char
                }else{
                    $isEnclosured = false;
                }
            }else {
                $addChar=$char;
            }
        }else {
            if($char==$enclosureChar) {
                $isEnclosured = true;
            }else {

                if($char==$separatorChar) {

                    $array[$rowIndex][$columnIndex] = $fieldValue;
                    $fieldValue="";

                    $columnIndex++;
                }elseif($char==$newlineChar) {
                    echo $char;
                    $array[$rowIndex][$columnIndex] = $fieldValue;
                    $fieldValue="";
                    $columnIndex=0;
                    $rowIndex++;
                }else {
                    $addChar=$char;
                }
            }
        }
        if($addChar!=""){
            $fieldValue.=$addChar;

        }
    }

    if($fieldValue) { // save last field
        $array[$rowIndex][$columnIndex] = $fieldValue;
    }
    return $array;
}
knagode
la source
16
$arrayFromCSV =  array_map('str_getcsv', file('/path/to/file.csv'));
Ivan G
la source
1
Bravo
14

Ancienne question, mais toujours d'actualité pour les utilisateurs de PHP 5.2. str_getcsv est disponible depuis PHP 5.3. J'ai écrit une petite fonction qui fonctionne avec fgetcsv lui-même.

Voici ma fonction de https://gist.github.com/4152628 :

function parse_csv_file($csvfile) {
    $csv = Array();
    $rowcount = 0;
    if (($handle = fopen($csvfile, "r")) !== FALSE) {
        $max_line_length = defined('MAX_LINE_LENGTH') ? MAX_LINE_LENGTH : 10000;
        $header = fgetcsv($handle, $max_line_length);
        $header_colcount = count($header);
        while (($row = fgetcsv($handle, $max_line_length)) !== FALSE) {
            $row_colcount = count($row);
            if ($row_colcount == $header_colcount) {
                $entry = array_combine($header, $row);
                $csv[] = $entry;
            }
            else {
                error_log("csvreader: Invalid number of columns at line " . ($rowcount + 2) . " (row " . ($rowcount + 1) . "). Expected=$header_colcount Got=$row_colcount");
                return null;
            }
            $rowcount++;
        }
        //echo "Totally $rowcount rows found\n";
        fclose($handle);
    }
    else {
        error_log("csvreader: Could not read CSV \"$csvfile\"");
        return null;
    }
    return $csv;
}

Retour

Commencez à lire CSV

Array
(
    [0] => Array
        (
            [vid] => 
            [agency] => 
            [division] => Division
            [country] => 
            [station] => Duty Station
            [unit] => Unit / Department
            [grade] => 
            [funding] => Fund Code
            [number] => Country Office Position Number
            [wnumber] => Wings Position Number
            [title] => Position Title
            [tor] => Tor Text
            [tor_file] => 
            [status] => 
            [datetime] => Entry on Wings
            [laction] => 
            [supervisor] => Supervisor Index Number
            [asupervisor] => Alternative Supervisor Index
            [author] => 
            [category] => 
            [parent] => Reporting to Which Position Number
            [vacant] => Status (Vacant / Filled)
            [index] => Index Number
        )

    [1] => Array
        (
            [vid] => 
            [agency] => WFP
            [division] => KEN Kenya, The Republic Of
            [country] => 
            [station] => Nairobi
            [unit] => Human Resources Officer P4
            [grade] => P-4
            [funding] => 5000001
            [number] => 22018154
            [wnumber] => 
            [title] => Human Resources Officer P4
            [tor] => 
            [tor_file] => 
            [status] => 
            [datetime] => 
            [laction] => 
            [supervisor] => 
            [asupervisor] => 
            [author] => 
            [category] => Professional
            [parent] => 
            [vacant] => 
            [index] => xxxxx
        )
) 
Manu Manjunath
la source
Btw, vous pouvez ajouter des paramètres facultatifs à fgetcsv pour changer le délimiteur, le caractère de clôture, etc.
Manu Manjunath
4

Essaye ça..

function getdata($csvFile){
    $file_handle = fopen($csvFile, 'r');
    while (!feof($file_handle) ) {
        $line_of_text[] = fgetcsv($file_handle, 1024);
    }
    fclose($file_handle);
    return $line_of_text;
}


// Set path to CSV file
$csvFile = 'test.csv';

$csv = getdata($csvFile);
echo '<pre>';
print_r($csv);
echo '</pre>';

Array
(
    [0] => Array
        (
            [0] => Project
            [1] => Date
            [2] => User
            [3] => Activity
            [4] => Issue
            [5] => Comment
            [6] => Hours
        )

    [1] => Array
        (
            [0] => test
            [1] => 04/30/2015
            [2] => test
            [3] => test
            [4] => test
            [5] => 
            [6] => 6.00
        ));
Deenadhayalan Manoharan
la source
3

Cette fonction renverra un tableau avec des valeurs d'en-tête sous forme de clés de tableau.

function csv_to_array($file_name) {
        $data =  $header = array();
        $i = 0;
        $file = fopen($file_name, 'r');
        while (($line = fgetcsv($file)) !== FALSE) {
            if( $i==0 ) {
                $header = $line;
            } else {
                $data[] = $line;        
            }
            $i++;
        }
        fclose($file);
        foreach ($data as $key => $_value) {
            $new_item = array();
            foreach ($_value as $key => $value) {
                $new_item[ $header[$key] ] =$value;
            }
            $_data[] = $new_item;
        }
        return $_data;
    }
sameerali
la source
3

Pour obtenir un tableau avec les bonnes clés, vous pouvez essayer ceci:

// Open file
$file = fopen($file_path, 'r');

// Headers
$headers = fgetcsv($file);

// Rows
$data = [];
while (($row = fgetcsv($file)) !== false)
{
    $item = [];
    foreach ($row as $key => $value)
        $item[$headers[$key]] = $value ?: null;
    $data[] = $item;
}

// Close file
fclose($file);
clem
la source
1

Veuillez trouver ci-dessous un lien vers la fonction de @knagode, améliorée avec un paramètre de saut de lignes. https://gist.github.com/gabrieljenik/47fc38ae47d99868d5b3#file-csv_to_array

<?php
    /**
     * Convert a CSV string into an array.
     * 
     * @param $string
     * @param $separatorChar
     * @param $enclosureChar
     * @param $newlineChar
     * @param $skip_rows
     * @return array
     */
    public static function csvstring_to_array($string, $skip_rows = 0, $separatorChar = ';', $enclosureChar = '"', $newlineChar = "\n") {
        // @author: Klemen Nagode 
        // @source: http://stackoverflow.com/questions/1269562/how-to-create-an-array-from-a-csv-file-using-php-and-the-fgetcsv-function
        $array = array();
        $size = strlen($string);
        $columnIndex = 0;
        $rowIndex = 0;
        $fieldValue="";
        $isEnclosured = false;
        for($i=0; $i<$size;$i++) {

            $char = $string{$i};
            $addChar = "";

            if($isEnclosured) {
                if($char==$enclosureChar) {

                    if($i+1<$size && $string{$i+1}==$enclosureChar){
                        // escaped char
                        $addChar=$char;
                        $i++; // dont check next char
                    }else{
                        $isEnclosured = false;
                    }
                }else {
                    $addChar=$char;
                }
            }else {
                if($char==$enclosureChar) {
                    $isEnclosured = true;
                }else {

                    if($char==$separatorChar) {

                        $array[$rowIndex][$columnIndex] = $fieldValue;
                        $fieldValue="";

                        $columnIndex++;
                    }elseif($char==$newlineChar) {
                        echo $char;
                        $array[$rowIndex][$columnIndex] = $fieldValue;
                        $fieldValue="";
                        $columnIndex=0;
                        $rowIndex++;
                    }else {
                        $addChar=$char;
                    }
                }
            }
            if($addChar!=""){
                $fieldValue.=$addChar;

            }
        }

        if($fieldValue) { // save last field
            $array[$rowIndex][$columnIndex] = $fieldValue;
        }


        /**
         * Skip rows. 
         * Returning empty array if being told to skip all rows in the array.
         */ 
        if ($skip_rows > 0) {
            if (count($array) == $skip_rows)
                $array = array();
            elseif (count($array) > $skip_rows)
                $array = array_slice($array, $skip_rows);           

        }

        return $array;
    }
Gabriel
la source
1
Dans stackoverflow, veuillez élaborer davantage plutôt que de fournir un lien uniquement.
Paul Lo le
1

Je suis venu avec ce code assez basique. Je pense que cela pourrait être utile à n'importe qui.

$link = "link to the CSV here"
$fp = fopen($link, 'r');

while(($line = fgetcsv($fp)) !== FALSE) {
    foreach($line as $key => $value) {
        echo $key . " - " . $value . "<br>";
    }
}


fclose($fp);
grc
la source
1

Si vous voulez que chaque ligne soit dans un tableau et chaque cellule de la ligne dans un tableau:

$file = fopen('csvFile.csv', 'r');              // Open the file                     
while (($line = fgetcsv($file)) !== FALSE) {    // Read one line
    $array[] =$line;                            // Add the line in the main array
}
echo '<pre>';
print_r($array);   //print it out
echo '</pre>'; 
fclose($file);
Pour de bon
la source
0

Essayez ce code:

function readCsv($file)
{
    if (($handle = fopen($file, 'r')) !== FALSE) {
        while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
            print_r(lineArray);
        }
        fclose($handle);
    }
}
Indrajeet Singh
la source
1
Quelle est la raison de publier exactement la même réponse à la question appliquée?
pinepain
0
 function csvToArray($path)
{
    try{
        $csv = fopen($path, 'r');
        $rows = [];
        $header = [];
        $index = 0;
        while (($line = fgetcsv($csv)) !== FALSE) {
            if ($index == 0) {
                $header = $line;
                $index = 1;
            } else {
                $row = [];
                for ($i = 0; $i < count($header); $i++) {
                    $row[$header[$i]] = $line[$i];
                }
                array_push($rows, $row);
            }
        }
        return $rows;
    }catch (Exception $exception){
        return false;
    }
}
ghak
la source
0
convertToArray(file_get_content($filename));

function convertToArray(string $content): array
{
   $data = str_getcsv($content,"\n");
   array_walk($data, function(&$a) use ($data) {
       $a = str_getcsv($a);
   });

   return $data;
}
Kamil Sułek
la source
quelle est la question?
SpongePablo
Voir " Expliquer les réponses entièrement basées sur le code ". Bien que cela puisse être techniquement correct, cela n'explique pas pourquoi cela résout le problème ou devrait être la réponse choisie. Nous devons éduquer en plus pour aider à résoudre le problème.
le Tin Man