PHP ve fgetcsv işlevi kullanılarak bir CSV dosyasından bir dizi nasıl oluşturulur


106

Birisi fgetcsv kullanarak bir CSV dosyasından bir dizi oluşturmak için bir kod sağlayabilir mi?

Basit bir CSV dosyasından bir dizi oluşturmak için aşağıdaki kodu kullandım, ancak alanlarımdan birinde birden çok virgül (adresler gibi) olduğunda doğru çalışmıyor.

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

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

* Ayrıca str_getcsv, barındırma hizmetim tarafından desteklenmiyor.

Yukarıdaki kod, aşağıdaki CSV dosyası örneğiyle çalışmaz. Birinci sütun isim, ikinci sütun adres, üçüncü sütun medeni durumdur.

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

2
PHP 5.2 ile mi takıldınız? Senin için hissediyorum, barındırma sağlayıcımla aynı gemideyim.
Adam F

Bu yardımcıyı kullanabilirsiniz: github.com/rap2hpoutre/csv-to-associative-array
rap-2-h

Yanıtlar:


179

Başlığınızda da söylediğiniz gibi, fgetcsv gidilecek yoldur. Kullanımı oldukça kolay.

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

fopen()Başarısız olması durumunda oraya daha fazla hata denetimi koymak isteyeceksiniz , ancak bu, bir CSV dosyasını satır satır okumak ve satırı bir diziye ayrıştırmak için işe yarar.


Teşekkürler Dave, ancak örneğiniz yalnızca şu üç konumu olan bir dizi sağlar: $ line [0], $ line [1] ve $ line [2]. Bu ilk satır için sorun değil ama 2., 3., 4. vb. Satırlar için ayrı pozisyonlar oluşturmam gerekiyor. Bu şekilde hatları ayrı ayrı değiştirebilirim. Umarım mantıklıdır
Thomas

7
@Thomas Bir dizi ad, adres ve duruma ihtiyacınız varsa, yukarıda yaptığınız şeyi yapabilirsiniz: list($names[], $addresses[], $statuses[]) = $line;
Dave DeLong

Tekrar teşekkürler Dave! Bu beni heyecanlandırıyordu.
Thomas

Bu işlevle ilgili bir sorum var, CSV alanlarından birinde yeni bir satır varsa, şu anda satırı tek bir kayıt olarak ayrıştıracak mı? Yoksa bunun yerine iki (karıştırılmış) kayıt mı döndürür?
Alix Axel

neden sonunda kapatmamız gerekiyor?
kızgın kivi

55

Str_getcsv () sözdiziminin çok daha temiz olduğunu düşünüyorum, ayrıca CSV'nin dosya sisteminde depolanmasını gerektirmiyor.

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

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

Veya satır satır çözüm için:

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

Veya str_getcsv () içermeyen satır satır çözüm için:

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

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

fclose($file);

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

2
Bilginize: str_getcsv () yalnızca PHP 5.3.0'dan itibaren mevcuttur. Üzerinde çalıştığım proje 1 sürüm DOH tarafından kaçırıldı! (5.2.9 atm kullanıyoruz).
Jim Ford

Hafıza kısıtlamanız yoksa bu mükemmel. Fgetcsv çözümü herhangi bir donanım yapılandırmasıyla çalışır.
Sp4cecat

4
DİKKAT! str_getcsv ile satır sonlarını göz ardı etmesine neden olan bir hata var: bugs.php.net/bug.php?id=55763&edit=1
RJD22

Şunları yapabileceğinizi unutmayın: while (! Feof ($ dosya)) {$ csv [] = fgetcsv ($ dosya); } while yerine (($ sonuç = fgetcsv ($ dosya))! == yanlış) {$ csv [] = $ sonuç; }
David G

23

Bir csv dizesini diziye dönüştürecek bir işlev oluşturdum. İşlev, özel karakterlerden nasıl kaçılacağını bilir ve muhafaza karakterleri ile veya bunlar olmadan çalışır.

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

Bunu csv örneğinizle denedim ve beklendiği gibi çalışıyor!

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;
}


14

Eski soru, ancak yine de PHP 5.2 kullanıcıları için geçerli. str_getcsv, PHP 5.3'te mevcuttur. Fgetcsv ile çalışan küçük bir işlev yazdım.

Https://gist.github.com/4152628 adresindeki işlevim aşağıdadır :

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;
}

İadeler

CSV'yi Okumaya Başlayın

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
        )
) 

Btw, sınırlayıcıyı, muhafaza karakterini vb. Değiştirmek için fgetcsv'ye isteğe bağlı parametreler ekleyebilirsiniz.
Manu Manjunath

4

Bunu dene..

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
        ));

3

Bu işlev, başlık değerleri ile dizi anahtarları olarak bir dizi döndürecektir.

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;
    }

3

Doğru tuşlara sahip bir dizi elde etmek için şunu deneyebilirsiniz:

// 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);

1

Lütfen satırları atlama parametresiyle geliştirilmiş @knagode işlevinin bağlantısının altına gelin. 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;
    }

1
Stackoverflow'da, lütfen yalnızca bir bağlantı sağlamak yerine daha fazla ayrıntı verin.
Paul Lo

1

Bu oldukça basit kodu buldum. Bence herkes için faydalı olabilir.

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

1

Her satırın bir dizide olmasını ve dizideki satırdaki her hücrenin olmasını istiyorsanız:

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

0

Bu kodu deneyin:

function readCsv($file)
{
    if (($handle = fopen($file, 'r')) !== FALSE) {
        while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
            print_r(lineArray);
        }
        fclose($handle);
    }
}

1
Aynı yanıtı sorgulayan kişiyi göndermenin nedeni nedir?
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;
    }
}

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;
}

soru nedir?
SpongePablo

Bkz. " Tamamen kod tabanlı yanıtları açıklama ". Bu teknik olarak doğru olsa da, sorunun neden çözüldüğünü veya seçilen cevap olması gerektiğini açıklamaz. Sorunu çözmeye yardımcı olmanın yanı sıra eğitmeliyiz.
Teneke Adam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.