PHP 및 fgetcsv 함수를 사용하여 CSV 파일에서 배열을 만드는 방법


106

누군가 fgetcsv를 사용하여 CSV 파일에서 배열을 만드는 코드를 친절하게 제공 할 수 있습니까?

다음 코드를 사용하여 간단한 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
랩 - 2 시간

답변:


179

제목에서 말했듯이 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]의 세 위치가있는 배열 만 제공합니다. 첫 번째 줄은 괜찮지 만 두 번째, 세 번째, 네 번째 줄에 대해 별도의 위치를 ​​만들어야합니다. 이렇게하면 선을 개별적으로 조작 할 수 있습니다. 이치
Thomas

7
당신은 이름, 주소, 및 상태의 배열을해야하는 경우 @Thomas, 당신은 당신이 위에서 무슨 일을하는지 수행 할 수 있습니다 list($names[], $addresses[], $statuses[]) = $line;
데이브 드롱

다시 한번 감사드립니다 Dave! 그것은 나를 넘어 뜨리고 있었다.
Thomas

이 기능에 대한 질문이 있습니다. CSV 필드 중 하나에 새 줄이있는 경우 현재 줄을 단일 레코드로 구문 분석합니까? 아니면 대신 두 개의 (얽힌) 레코드를 반환합니까?
Alix Axel 2013 년

왜 우리는 마지막에 fclose를해야합니까?
화가 키위

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
참고 : str_getcsv ()는 PHP 5.3.0부터 만 사용할 수 있습니다. 내가 작업중인 프로젝트는 DOH 1 개 버전으로 놓쳤습니다! (우리는 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; }
데이비드 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에 옵션 PARAMS을 추가 할 수 있습니다
마누 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 2014-07-25

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.