Cách tạo mảng từ tệp CSV bằng PHP và hàm fgetcsv


106

Ai đó có thể vui lòng cung cấp mã để tạo một mảng từ tệp CSV bằng cách sử dụng fgetcsv không?

Tôi đã sử dụng mã sau để tạo một mảng từ một tệp CSV đơn giản, nhưng nó không hoạt động đúng khi một trong các trường của tôi có nhiều dấu phẩy - chẳng hạn như địa chỉ.

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

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

* Ngoài ra, str_getcsv không được dịch vụ lưu trữ của tôi hỗ trợ.

Mã trên không hoạt động với ví dụ tệp CSV sau. Cột đầu tiên là tên, cột thứ hai là địa chỉ, cột thứ ba là tình trạng hôn nhân.

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
Bạn gặp khó khăn với PHP 5.2 hả? Tôi cảm thấy đối với bạn, tôi đang cùng thuyền với nhà cung cấp dịch vụ lưu trữ của mình.
Adam F

Bạn có thể sử dụng trình trợ giúp này: github.com/rap2hpoutre/csv-to-associative-array
rap-2-h

Câu trả lời:


179

Giống như bạn đã nói trong tiêu đề của mình, fgetcsv là con đường để đi. Nó khá dễ sử dụng.

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

Bạn sẽ muốn kiểm tra lỗi nhiều hơn trong trường hợp fopen()không thành công, nhưng điều này hoạt động để đọc từng dòng tệp CSV và phân tích cú pháp dòng đó thành một mảng.


Cảm ơn Dave nhưng ví dụ của bạn chỉ cung cấp một mảng có ba vị trí sau: $ line [0], $ line [1] và $ line [2]. Điều đó là tốt cho dòng đầu tiên, nhưng tôi cần tạo các vị trí riêng biệt cho các dòng thứ 2, 3, 4, v.v. Bằng cách đó tôi có thể thao tác các dòng riêng biệt. Hy vọng điều đó có ý nghĩa
Thomas

7
@Thomas Nếu bạn cần một loạt các tên, địa chỉ, và trạng thái, bạn chỉ có thể làm những gì bạn đang làm trên: list($names[], $addresses[], $statuses[]) = $line;
Dave DeLong

Cảm ơn một lần nữa Dave! Điều đó đã làm tôi vấp ngã.
Thomas

Tôi có câu hỏi về chức năng này, nếu một trong các trường CSV có một dòng mới trong đó, nó hiện có phân tích cú pháp dòng đó thành một bản ghi duy nhất không? Hay thay vào đó nó sẽ trả về hai bản ghi (bị xáo trộn)?
Alix Axel

tại sao chúng ta cần fclose ở cuối?
kiwi giận dữ

55

Tôi nghĩ rằng cú pháp str_getcsv () gọn gàng hơn nhiều, nó cũng không yêu cầu CSV phải được lưu trữ trong hệ thống tệp.

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

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

Hoặc đối với giải pháp từng dòng:

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

Hoặc đối với giải pháp từng dòng một không có 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 () chỉ có sẵn từ phiên bản PHP 5.3.0 trở đi. Dự án tôi đang thực hiện đã bỏ lỡ nó bởi 1 phiên bản DOH! (chúng tôi đang sử dụng 5,2,9 atm).
Jim Ford

Điều đó thật tuyệt vời, trừ khi bạn bị hạn chế về bộ nhớ. Giải pháp fgetcsv hoạt động với bất kỳ cấu hình phần cứng nào.
Sp4cecat

4
CẨN THẬN! có một lỗi với str_getcsv khiến nó bỏ qua phần cuối của dòng: bug.php.net/bug.php?id=55763&edit=1
RJD22

Lưu ý rằng bạn có thể làm: while (! Feof ($ file)) {$ csv [] = fgetcsv ($ file); } thay vì while (($ result = fgetcsv ($ file))! == false) {$ csv [] = $ result; }
David G

23

Tôi đã tạo một hàm sẽ chuyển đổi một chuỗi csv thành một mảng. Hàm biết cách thoát các ký tự đặc biệt và nó hoạt động với hoặc không có các ký tự bao vây.

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

Tôi đã thử nó với mẫu csv của bạn và nó hoạt động như mong đợi!

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

Câu hỏi cũ, nhưng vẫn có liên quan cho người dùng PHP 5.2. str_getcsv có sẵn từ PHP 5.3. Tôi đã viết một hàm nhỏ hoạt động với chính fgetcsv.

Dưới đây là chức năng của tôi từ 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;
}

Lợi nhuận

Bắt đầu đọc 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, bạn có thể thêm các thông số tùy chọn vào fgetcsv để thay đổi dấu phân cách, ký tự bao vây, v.v.
Manu Manjunath

4

Thử cái này..

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

Hàm này sẽ trả về mảng có giá trị Header dưới dạng các khóa mảng.

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

Để có được một mảng với các phím phù hợp, bạn có thể thử cách này:

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

Vui lòng điền vào bên dưới một liên kết đến hàm từ @knagode, được nâng cao với tham số hàng bỏ qua. 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
Trong stackoverflow, vui lòng giải thích kỹ hơn thay vì chỉ cung cấp một liên kết.
Paul Lo

1

Tôi đã nghĩ ra mã khá cơ bản này. Tôi nghĩ rằng nó có thể hữu ích cho bất kỳ ai.

$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

Nếu bạn muốn mỗi dòng nằm trong một mảng và mỗi ô trong dòng trong mảng:

$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

Hãy thử mã này:

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

1
Lý do để đăng cùng một câu hỏi trả lời được áp dụng là gì?
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;
}

câu hỏi là gì
SpongePablo

Xem " Giải thích câu trả lời hoàn toàn dựa trên mã ". Mặc dù điều này có thể đúng về mặt kỹ thuật nhưng nó không giải thích tại sao nó giải quyết được vấn đề hoặc nên là câu trả lời được chọn. Chúng ta nên giáo dục ngoài việc giúp giải quyết vấn đề.
Tin Man
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.