วิธีสร้างอาร์เรย์จากไฟล์ CSV โดยใช้ PHP และฟังก์ชัน fgetcsv


107

ใครช่วยให้รหัสสร้างอาร์เรย์จากไฟล์ CSV โดยใช้ fgetcsv ได้ไหม

ฉันใช้รหัสต่อไปนี้เพื่อสร้างอาร์เรย์จากไฟล์ CSV ธรรมดา แต่มันใช้งานไม่ได้เมื่อฟิลด์หนึ่งของฉันมีเครื่องหมายจุลภาคหลายช่องเช่นที่อยู่

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

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

* นอกจากนี้บริการโฮสต์ของฉันไม่รองรับ str_getcsv

โค้ดด้านบนใช้ไม่ได้กับตัวอย่างไฟล์ CSV ต่อไปนี้ คอลัมน์แรกคือชื่อคอลัมน์ที่สองคือที่อยู่คอลัมน์ที่สามคือสถานภาพการสมรส

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 ใช่หรือไม่ ฉันรู้สึกแทนคุณฉันอยู่ในเรือลำเดียวกันกับผู้ให้บริการโฮสติ้งของฉัน
Adam F

คุณสามารถใช้ตัวช่วยนี้: github.com/rap2hpoutre/csv-to-associative-array
rap-2-h

คำตอบ:


180

เช่นเดียวกับที่คุณพูดในชื่อเรื่องfgetcsvคือหนทางที่จะไป มันค่อนข้างใช้งานง่าย

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

คุณจะต้องตรวจสอบข้อผิดพลาดเพิ่มเติมในกรณีที่fopen()ล้มเหลว แต่วิธีนี้ใช้ได้ผลในการอ่านไฟล์ CSV ทีละบรรทัดและแยกวิเคราะห์บรรทัดลงในอาร์เรย์


ขอบคุณ Dave แต่ตัวอย่างของคุณมีเฉพาะอาร์เรย์ที่มีสามตำแหน่งต่อไปนี้: $ line [0], $ line [1] และ $ line [2] นั่นใช้ได้สำหรับบรรทัดแรก แต่ฉันต้องสร้างตำแหน่งแยกสำหรับบรรทัดที่ 2, 3, 4 ฯลฯ ด้วยวิธีนี้ฉันสามารถจัดการเส้นแยกกันได้ หวังว่าจะสมเหตุสมผล
Thomas

7
@Thomas หากคุณต้องการอาร์เรย์ของชื่อที่อยู่และสถานะคุณสามารถทำสิ่งที่คุณทำด้านบน: list($names[], $addresses[], $statuses[]) = $line;
Dave DeLong

ขอบคุณอีกครั้ง Dave! นั่นทำให้ฉันสะดุด
Thomas

ฉันมีคำถามเกี่ยวกับฟังก์ชันนี้หากช่อง CSV ช่องใดช่องหนึ่งมีบรรทัดใหม่อยู่ในนั้นตอนนี้จะแยกวิเคราะห์บรรทัดเป็นระเบียนเดียวหรือไม่ หรือจะส่งคืนสองระเบียน (แหลกเหลว) แทน?
Alix Axel

ทำไมเราต้องปิดท้าย?
กีวีโกรธ

55

ฉันคิดว่าไวยากรณ์str_getcsv () นั้นสะอาดกว่ามาก แต่ก็ไม่จำเป็นต้องจัดเก็บ CSV ในระบบไฟล์

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

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

หรือสำหรับการแก้ปัญหาทีละบรรทัด:

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

หรือสำหรับโซลูชันทีละบรรทัดโดยไม่มี 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>';

2
FYI: str_getcsv () พร้อมใช้งานจาก PHP 5.3.0 บนเท่านั้น โครงการที่ฉันกำลังทำพลาดไป 1 เวอร์ชัน DOH! (เราใช้ 5.2.9 atm)
Jim Ford

ยอดเยี่ยมมากเว้นแต่คุณจะมีข้อ จำกัด ด้านความจำ โซลูชัน fgetcsv ทำงานร่วมกับการกำหนดค่าฮาร์ดแวร์ใด ๆ
Sp4cecat

4
ระวัง! มีข้อผิดพลาดกับ str_getcsv ที่ทำให้ไม่สนใจการสิ้นสุดบรรทัด: bugs.php.net/bug.php?id=55763&edit=1
RJD22

หมายเหตุคุณสามารถทำได้: while (! feof ($ file)) {$ csv [] = fgetcsv ($ file); } แทน while (($ result = fgetcsv ($ file))! == false) {$ csv [] = $ result; }
David G

23

ฉันได้สร้างฟังก์ชันที่จะแปลงสตริง csv เป็นอาร์เรย์ ฟังก์ชันนี้ทราบวิธีการหลีกเลี่ยงอักขระพิเศษและสามารถใช้งานได้โดยมีหรือไม่มีตัวอักษรกล่องหุ้ม

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

ฉันลองใช้กับตัวอย่าง csv ของคุณแล้วและได้ผลตามที่คาดไว้!

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

คำถามเก่า แต่ยังคงเกี่ยวข้องกับผู้ใช้ PHP 5.2 str_getcsv พร้อมใช้งานจาก PHP 5.3 ฉันได้เขียนฟังก์ชันเล็ก ๆ ที่ใช้ได้กับ fgetcsv เอง

ด้านล่างนี้คือฟังก์ชั่นของฉันจาก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;
}

ผลตอบแทน

เริ่มอ่าน 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
        )
) 

Btw คุณสามารถเพิ่มพารามิเตอร์เสริมให้กับ fgetcsv เพื่อเปลี่ยนตัวคั่นอักขระสิ่งที่แนบมาและอื่น ๆ
Manu Manjunath

4

ลองดูสิ ..

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

ฟังก์ชันนี้จะส่งคืนอาร์เรย์ที่มีค่าส่วนหัวเป็นคีย์อาร์เรย์

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

หากต้องการรับอาร์เรย์ที่มีคีย์ที่ถูกต้องคุณสามารถลองสิ่งนี้:

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

โปรดดูลิงก์ไปยังฟังก์ชันจาก @knagode ด้านล่างซึ่งปรับปรุงด้วยพารามิเตอร์การข้ามแถว 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 โปรดอธิบายให้ละเอียดมากกว่าที่จะระบุลิงก์เท่านั้น
Paul Lo

1

ฉันคิดรหัสพื้นฐานนี้ขึ้นมา ฉันคิดว่ามันน่าจะเป็นประโยชน์กับทุกคน

$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

หากคุณต้องการให้แต่ละบรรทัดอยู่ในอาร์เรย์และแต่ละเซลล์ในบรรทัดในอาร์เรย์:

$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

ลองใช้รหัสนี้:

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

1
อะไรคือเหตุผลในการโพสต์คำถามคำตอบเดียวกันที่ใช้?
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;
}

คำถามคืออะไร?
SpongePablo

ดู "การอธิบายคำตอบที่ใช้รหัสทั้งหมด " แม้ว่าสิ่งนี้อาจถูกต้องในทางเทคนิค แต่ก็ไม่ได้อธิบายว่าเหตุใดจึงแก้ปัญหาได้หรือควรเป็นคำตอบที่เลือก เราควรให้ความรู้นอกเหนือจากการช่วยแก้ปัญหา
The Tin Man
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.