2012-04-16 38 views
15

我有一個包含字段名稱的第一行的CSV。示例數據是...將CSV處理爲陣列,並使用列標題輸入密鑰

"Make","Model","Note" 
"Chevy","1500","loaded" 
"Chevy","2500","" 
"Chevy","","loaded" 

我需要我的數據格式化在鍵值對的數組中,其中鍵名是列標題。我想這將是這樣的第1行:

$array = [ 
    "Make" => "Chevy", 
    "Model" => "1500", 
    "Note" => "loaded" 
]; 

...第2行...

$array = [ 
    "Make" => "Chevy", 
    "Model" => "1500", 
    "Note" => "" 
]; 

...和第3行...

$array = [ 
    "Make" => "Chevy", 
    "Model" => "", 
    "Note" => "loaded" 
]; 

我我不知道如何做到這一點,而不是靜態 - 問題是與他們相關的數據列可能會改變從一個文件到下一個列重新安排,刪除或添加。

你的想法是非常感謝。

+0

你可能意味着2500在第二個數組示例中 – user1899415 2013-11-07 16:05:29

回答

39
$all_rows = array(); 
$header = fgetcsv($file); 
while ($row = fgetcsv($file)) { 
    $all_rows[] = array_combine($header, $row); 
} 
print_r($all_rows); 
+0

感謝您的及時響應。儘管我最後得到了關鍵數據,但這很接近。在任何返回的數組中看不到任何列標題。 – 2012-04-16 20:34:56

+1

@BitBucket:如果您執行'$ all_rows'中的數據轉儲,則應該看到一個包含以標題數據爲鍵的子數組的數組。 – 2012-04-16 20:39:28

+0

請注意,當您第一次創建它時,您需要運行$ header,以確保您給出沒有標題虛擬數據(如「未知」)的任何列。 $ x或數組合並將有不同的長度 – Titan 2016-09-22 09:58:22

27

PHP提供了你需要內SplFileObject什麼已經99.9%,可以通過從其延伸添加缺少的0.1%。在下面的例子CSVFile從它延伸:

$csv = new CSVFile('../data/test.csv'); 

foreach ($csv as $line) 
{ 
    var_dump($line); 
} 

與您的數據。例如:

array(3) { 
    ["Make"]=> string(5) "Chevy" 
    ["Model"]=> string(4) "1500" 
    ["Note"]=> string(6) "loaded" 
} 
array(3) { 
    ["Make"]=> string(5) "Chevy" 
    ["Model"]=> string(4) "2500" 
    ["Note"]=> string(0) "" 
} 
array(3) { 
    ["Make"]=> string(5) "Chevy" 
    ["Model"]=> string(0) "" 
    ["Note"]=> string(6) "loaded" 
} 

CSVFile被定義如下:

class CSVFile extends SplFileObject 
{ 
    private $keys; 

    public function __construct($file) 
    { 
     parent::__construct($file); 
     $this->setFlags(SplFileObject::READ_CSV); 
    } 

    public function rewind() 
    { 
     parent::rewind(); 
     $this->keys = parent::current(); 
     parent::next(); 
    } 

    public function current() 
    { 
     return array_combine($this->keys, parent::current()); 
    } 

    public function getKeys() 
    { 
     return $this->keys; 
    } 
} 

如果你做這樣一來,細節很好地封裝掉了。此外,更容易處理current()函數內的錯誤(例如計數不匹配),因此使用數據的代碼無需處理。

編輯:

然而給出的實施例是在短重新usablity方面。相反,從SplFileObject延長它的好得多總IT:

class KeyedArrayIterator extends IteratorIterator 
{ 
    private $keys; 

    public function rewind() 
    { 
     parent::rewind(); 
     $this->keys = parent::current(); 
     parent::next(); 
    } 

    public function current() 
    { 
     return array_combine($this->keys, parent::current()); 
    } 

    public function getKeys() 
    { 
     return $this->keys; 
    } 
} 

的代碼相同但被封裝在構造函數的細節被排除在外。這種減少允許更廣泛地使用該類型,例如,與(但不僅與)上述SplFileObject

$file = new SplFileObject('../data/test.csv'); 
$file->setFlags($file::READ_CSV); 

$csv = new KeyedArrayIterator($file); 

foreach ($csv as $line) { 
    var_dump($line); 
} 

如果現在聽起來太冗長,它可再次包裝再次給它一個更好的外觀:

class CSVFile extends KeyedArrayIterator 
{ 
    /** 
    * @param string $file 
    */ 
    public function __construct($file) 
    { 
     parent::__construct(new SplFileObject($file)); 
     $this->setFlags(SplFileObject::READ_CSV); 
    } 
} 

得益於標準裝修能力TraversableIterator的第一個示例的原始構造函數代碼可以僅複製100%的CSVFile

這最後此外還可以保持原有的代碼,使用CSVFile迭代器完好:

$csv = new CSVFile('../data/test.csv'); 

foreach ($csv as $line) { 
    var_dump($line); 
} 

所以只是一個快速重構,讓更多的代碼重用。你可以免費獲得KeyedArrayIterator

+1

非常不錯...... – 2012-11-26 17:15:45

+0

您是否可以爲了興趣而想出一種使這個句柄無標題CSV的方法? – 2012-11-26 17:17:11

+1

這非常簡單:省略'rewind'函數,並在構造函數中傳遞鍵。如果你需要更多的靈活性,我已經用一些例子把一些代碼加入到了要點中,但它仍然很漂亮:https://gist.github.com/4153380 – hakre 2012-11-27 09:59:19

0

嘗試使用此代碼:

$query = "SELECT * FROM datashep_AMS.COMPLETE_APPLICATIONS"; 
$export= mysql_query($query); 
$first = true; 
$temp = $export[0]; 
//echo "<pre>"; print_r($first); exit; 

header('Content-Type: text/csv'); 
header('Content-Disposition: attachment; filename=file.csv'); 
header('Pragma: no-cache'); 
header("Expires: 0"); 

$outstream = fopen("php://output", "w"); 



foreach($export as $result) 
{ 
    if($first){ 
     $titles = array(); 
     foreach($temp as $key=>$val){ 
      $titles[] = $key; 
     } 
     //print_r ($titles);exit; 
     fputcsv($outstream, $titles); 
    } 
    $first = false; 
    fputcsv($outstream, $result); 
} 

fclose($outstream); 

感謝

2
function processCsv($absolutePath) 
{ 
    $csv = array_map('str_getcsv', file($absolutePath)); 
    $headers = $csv[0]; 
    unset($csv[0]); 
    $rowsWithKeys = []; 
    foreach ($csv as $row) { 
     $newRow = []; 
     foreach ($headers as $k => $key) { 
      $newRow[$key] = $row[$k]; 
     } 
     $rowsWithKeys[] = $newRow; 
    } 
    return $rowsWithKeys; 
} 
1

在這一點上我假設你已經解決了這個問題,但認爲我會在解決這個建議的方式拋,可能不是最好/最優雅的解決方案,但它的確有訣竅:

$row = 1; 
$array = array(); 
$marray = array(); 
$handle = fopen('file.csv', 'r'); 
if ($handle !== FALSE) { 
    while (($data = fgetcsv($handle, 0, ',')) !== FALSE) { 
     if ($row === 1) { 
      $num = count($data); 
      for ($i = 0; $i < $num; $i++) { 
       array_push($array, $data[$i]); 
      } 
     } 
     else { 
      $c = 0; 
      foreach ($array as $key) { 
       $marray[$row - 1][$key] = $data[$c]; 
       $c++; 
      } 
     } 
     $row++; 
    } 
    echo '<pre>'; 
    print_r($marray); 
    echo '</pre>'; 
} 
4
$csv_data = array_map('str_getcsv', file('Book.csv'));// reads the csv file in php array 
$csv_header = $csv_data[0];//creates a copy of csv header array 
unset($csv_data[0]);//removes the header from $csv_data since no longer needed 
foreach($csv_data as $row){ 
    $row = array_combine($csv_header, $row);// adds header to each row as key 
    var_dump($row);//do something here with each row 
} 
0

試試這個

$csv = array_map("str_getcsv", file('file.csv', FILE_SKIP_EMPTY_LINES));  
$header = array_shift($csv); // get header from array 

foreach ($csv as $key => $value) {  
    $csv[$key] = array_combine($header, $value); 
    var_dump($csv[$key]['Model']); 
} 

var_dump($csv); 
0

在上面添庫珀的答案,而不是

$all_rows = array(); 
$header = null; 
while ($row = fgetcsv($file)) { 
    if ($header === null) { 
     $header = $row; 
     continue; 
    } 
    $all_rows[] = array_combine($header, $row); 
} 

我的代碼,在一個更優雅的和有效的方式:

$all_rows = array(); 
$header = fgetcsv($file); 
while ($row = fgetcsv($file)) { 
    $all_rows[] = array_combine($header, $row); 
}