Jak utworzyć tablicę z pliku CSV za pomocą PHP i funkcji fgetcsv

106

Czy ktoś może uprzejmie dostarczyć kod do utworzenia tablicy z pliku CSV przy użyciu fgetcsv?

Użyłem następującego kodu, aby utworzyć tablicę z prostego pliku CSV, ale nie działa poprawnie, gdy jedno z moich pól zawiera wiele przecinków - na przykład adresy.

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

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

* Ponadto moja usługa hostingowa nie obsługuje str_getcsv.

Powyższy kod nie działa z następującym przykładem pliku CSV. Pierwsza kolumna to nazwisko, druga adres, trzecia to stan cywilny.

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
Tomasz
źródło
2
Utknąłeś z PHP 5.2? Współczuję wam, jestem na tej samej łodzi z moim dostawcą usług hostingowych.
Adam F
Możesz skorzystać z tego pomocnika: github.com/rap2hpoutre/csv-to-associative-array
rap-2-h

Odpowiedzi:

179

Jak powiedziałeś w swoim tytule, fgetcsv jest drogą do zrobienia. Jest bardzo łatwy w użyciu.

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

Będziesz chciał umieścić tam więcej sprawdzania błędów na wypadek fopen()niepowodzenia, ale to działa, aby odczytać plik CSV wiersz po wierszu i przeanalizować wiersz do tablicy.

Dave DeLong
źródło
Dzięki, Dave, ale twój przykład zawiera tylko tablicę z następującymi trzema pozycjami: $ line [0], $ line [1] i $ line [2]. To jest w porządku dla pierwszej linii, ale muszę utworzyć osobne pozycje dla drugiej, trzeciej, czwartej itd. Linii. W ten sposób mogę osobno manipulować liniami. Mam nadzieję, że to ma sens
Thomas
7
@Thomas Jeśli potrzebujesz tablicy nazwisk, adresów i statusów, możesz po prostu zrobić to, co robisz powyżej: list($names[], $addresses[], $statuses[]) = $line;
Dave DeLong
Jeszcze raz dziękuję Dave! To mnie podrywało.
Thomas
Mam pytanie dotyczące tej funkcji, jeśli jedno z pól CSV ma w sobie nową linię, czy będzie ona obecnie analizować linię jako pojedynczy rekord? Czy zamiast tego zwróci dwa (zniekształcone) rekordy?
Alix Axel
dlaczego musimy zamknąć na końcu?
angry kiwi
55

Myślę, że składnia str_getcsv () jest znacznie czystsza, nie wymaga również przechowywania pliku CSV w systemie plików.

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

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

Lub w przypadku rozwiązania linia po linii:

$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>';

Lub dla rozwiązania linia po linii bez 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
źródło
2
Do Twojej wiadomości: str_getcsv () jest dostępna tylko od PHP 5.3.0. Projekt, nad którym pracuję, przegapił 1 wersję DOH! (używamy 5,2,9 atm).
Jim Ford
To świetnie, chyba że masz ograniczenia pamięci. Rozwiązanie fgetcsv działa z każdą konfiguracją sprzętową.
Sp4cecat
4
STRZEC SIĘ! w str_getcsv jest błąd, który powoduje, że ignoruje ono zakończenia linii: bugs.php.net/bug.php?id=55763&edit=1
RJD22
Zauważ, że możesz: while (! Feof ($ file)) {$ csv [] = fgetcsv ($ file); } zamiast while (($ wynik = fgetcsv ($ plik))! == false) {$ csv [] = $ wynik; }
David G.
23

Stworzyłem funkcję, która skonwertuje ciąg csv na tablicę. Funkcja wie, jak unikać znaków specjalnych i działa ze znakami obudowy lub bez.

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

Wypróbowałem to z twoją próbką CSV i działa zgodnie z oczekiwaniami!

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
źródło
16
$arrayFromCSV =  array_map('str_getcsv', file('/path/to/file.csv'));
Ivan G.
źródło
1
Kciuki w górę za prostotę
kudlohlavec
14

Stare pytanie, ale nadal aktualne dla użytkowników PHP 5.2. str_getcsv jest dostępny od PHP 5.3. Napisałem małą funkcję, która działa z samym fgetcsv.

Poniżej moja funkcja z 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;
}

Zwroty

Rozpocznij czytanie 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
źródło
Przy okazji, możesz dodać opcjonalne parametry do fgetcsv, aby zmienić ogranicznik, znak obudowy itp.
Manu Manjunath
4

Spróbuj tego..

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
źródło
3

Ta funkcja zwróci tablicę z wartościami nagłówka jako klucze tablicy.

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
źródło
3

Aby uzyskać tablicę z odpowiednimi kluczami, możesz spróbować tego:

// 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
źródło
1

Poniżej znajduje się link do funkcji z @knagode, wzbogaconej o parametr pomijania wierszy. 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
źródło
1
W przypadku przepełnienia stosu prosimy o więcej informacji niż podawanie samego łącza.
Paul Lo
1

Wymyśliłem ten dość podstawowy kod. Myślę, że może się przydać każdemu.

$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
źródło
1

Jeśli chcesz, aby każda linia była w tablicy, a każda komórka w linii w tablicy:

$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);
Na dobre
źródło
0

Wypróbuj ten kod:

function readCsv($file)
{
    if (($handle = fopen($file, 'r')) !== FALSE) {
        while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
            print_r(lineArray);
        }
        fclose($handle);
    }
}
Indrajeet Singh
źródło
1
Jaki jest powód, aby opublikować dokładnie taką samą odpowiedź, jaka została zastosowana?
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
źródło
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
źródło
Jakie jest pytanie?
SpongePablo
Zobacz „ Wyjaśnianie odpowiedzi opartych wyłącznie na kodzie ”. Chociaż może to być technicznie poprawne, nie wyjaśnia, dlaczego rozwiązuje problem lub powinno być wybraną odpowiedzią. Powinniśmy dodatkowo kształcić, aby pomóc rozwiązać problem.
Tin Man