Cara membuat array dari file CSV menggunakan PHP dan fungsi fgetcsv

106

Bisakah seseorang dengan ramah memberikan kode untuk membuat array dari file CSV menggunakan fgetcsv?

Saya telah menggunakan kode berikut untuk membuat larik dari file CSV sederhana, tetapi tidak berfungsi dengan benar ketika salah satu bidang saya memiliki banyak koma - seperti alamat.

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

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

* Selain itu, str_getcsv tidak didukung oleh layanan hosting saya.

Kode di atas tidak berfungsi dengan contoh file CSV berikut. Kolom pertama adalah nama, kolom kedua adalah alamat, kolom ketiga adalah status perkawinan.

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
sumber
2
Terjebak dengan PHP 5.2 eh? Saya merasa untuk Anda, saya berada di perahu yang sama dengan penyedia hosting saya.
Adam F
Anda dapat menggunakan pembantu ini: github.com/rap2hpoutre/csv-to-associative-array
rap-2-h

Jawaban:

179

Seperti yang Anda katakan di judul Anda, fgetcsv adalah cara yang tepat. Sangat mudah digunakan.

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

Anda akan ingin meletakkan lebih banyak pemeriksaan kesalahan di sana jika fopen()gagal, tetapi ini berfungsi untuk membaca file CSV baris demi baris dan mengurai baris menjadi array.

Dave DeLong
sumber
Terima kasih Dave tetapi contoh Anda hanya menyediakan larik dengan tiga posisi berikut: $ line [0], $ line [1], dan $ line [2]. Itu bagus untuk baris pertama, tetapi saya perlu membuat posisi terpisah untuk baris ke-2, ke-3, ke-4, dll. Dengan cara itu saya dapat memanipulasi garis secara terpisah. Harapan yang masuk akal
Thomas
7
@ Thomas Jika Anda memerlukan serangkaian nama, alamat, dan status, Anda dapat melakukan apa yang Anda lakukan di atas: list($names[], $addresses[], $statuses[]) = $line;
Dave DeLong
Terima kasih sekali lagi Dave! Itu membuatku tersandung.
Thomas
Saya mendapat pertanyaan tentang fungsi ini, jika salah satu kolom CSV memiliki baris baru di dalamnya, apakah saat ini akan mengurai baris sebagai satu record? Atau akankah itu mengembalikan dua catatan (rusak) sebagai gantinya?
Alix Axel
mengapa kita harus menutup akhirnya?
kiwi marah
55

Saya pikir sintaks str_getcsv () jauh lebih bersih, juga tidak memerlukan CSV untuk disimpan di sistem file.

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

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

Atau untuk solusi baris demi baris:

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

Atau untuk solusi baris demi baris tanpa 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
sumber
2
FYI: str_getcsv () hanya tersedia dari PHP 5.3.0. Proyek yang saya kerjakan melewatkannya dengan 1 versi DOH! (kami menggunakan 5.2.9 atm).
Jim Ford
Itu luar biasa, kecuali Anda memiliki batasan memori. Solusi fgetcsv bekerja dengan konfigurasi perangkat keras apa pun.
Sp4cecat
4
AWAS! ada bug dengan str_getcsv yang membuatnya mengabaikan akhir baris: bugs.php.net/bug.php?id=55763&edit=1
RJD22
Catatan yang dapat Anda lakukan: while (! Feof ($ file)) {$ csv [] = fgetcsv ($ file); } bukannya while (($ result = fgetcsv ($ file))! == false) {$ csv [] = $ result; }
David G
23

Saya telah membuat fungsi yang akan mengubah string csv menjadi array. Fungsi tersebut mengetahui cara keluar dari karakter khusus, dan berfungsi dengan atau tanpa karakter enklosur.

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

Saya mencobanya dengan sampel csv Anda dan berfungsi seperti yang diharapkan!

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
sumber
16
$arrayFromCSV =  array_map('str_getcsv', file('/path/to/file.csv'));
Ivan G
sumber
1
Jempol untuk kesederhanaan
kudlohlavec
14

Pertanyaan lama, tapi masih relevan untuk pengguna PHP 5.2. str_getcsv tersedia dari PHP 5.3. Saya telah menulis sebuah fungsi kecil yang bekerja dengan fgetcsv itu sendiri.

Di bawah ini adalah fungsi saya dari 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;
}

Kembali

Mulailah Membaca 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
sumber
Btw, Anda dapat menambahkan parameter opsional ke fgetcsv untuk mengubah pembatas, karakter enklosur, dll.
Manu Manjunath
4

Coba ini..

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
sumber
3

Fungsi ini akan mengembalikan array dengan nilai Header sebagai kunci array.

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
sumber
3

Untuk mendapatkan array dengan kunci yang tepat, Anda dapat mencoba ini:

// 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
sumber
1

Harap fin di bawah tautan ke fungsi dari @knagode, ditingkatkan dengan parameter lewati baris. 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
sumber
1
Dalam stackoverflow, harap jelaskan lebih dari sekadar memberikan tautan.
Paul Lo
1

Saya menemukan kode yang cukup mendasar ini. Saya pikir ini bisa bermanfaat bagi siapa saja.

$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
sumber
1

Jika Anda ingin setiap baris berada dalam array, dan setiap sel dalam baris dalam array:

$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);
ForGood
sumber
0

Coba kode ini:

function readCsv($file)
{
    if (($handle = fopen($file, 'r')) !== FALSE) {
        while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
            print_r(lineArray);
        }
        fclose($handle);
    }
}
Indrajeet Singh
sumber
1
Apa alasan untuk memposting pertanyaan dengan jawaban yang sama persis diterapkan?
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
sumber
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
sumber
apa pertanyaannya?
SpongePablo
Lihat " Menjelaskan jawaban yang seluruhnya berbasis kode ". Meskipun ini mungkin secara teknis benar, ini tidak menjelaskan mengapa ini menyelesaikan masalah atau harus menjadi jawaban yang dipilih. Kita harus mendidik selain membantu memecahkan masalah.
Tin Man