今天遇到一個在 Load balancer 上的網站,採用 PHP 5 的 A 主機網頁正常,但使用 PHP 7 的 B 主機版面就怪怪的。追蹤了一下,看起來是 fgetcsv() 出問題,沒有正常解析。我們的 CSV 檔是 Big5 編碼的,看起來是解析了某個中文欄位之後,後續欄位就有異常。

上網查了一下,找到《PHP讀取BIG5編碼的CSV檔》,裡面提到:

「但如果 CSV 檔是 BIG5 編碼,當中文字中有包含反斜線(\)字元的衝碼字,
可能會使 fgetcsv() 解析出來的資料欄位數量不正確。
可發現第 5 個脫逸參數預設是反斜線(\),所以當解析到包含反斜線(\)的 BIG5 中文字時,
雖然可以解析,但解析出來的資料不是預期的,該行解析出的欄位數也會是錯的。」

 

因為 PHP7 的 fgetcsv() 和 PHP5 fgetcsv() 的參數個數不同,所以要加上這樣的 function:

<?php
function __fgetcsv(&$handle, $length = null, $d = ",", $e = '"') {
  $d = preg_quote($d);
  $e = preg_quote($e);
  $_line = "";
  $eof=false;
  while ($eof != true) {
    $_line .= (empty ($length) ? fgets($handle) : fgets($handle, $length));
    $itemcnt = preg_match_all('/' . $e . '/', $_line, $dummy);
    if ($itemcnt % 2 == 0){
      $eof = true;
    }
  }
 
  $_csv_line = preg_replace('/(?: |[ ])?$/', $d, trim($_line));
 
  $_csv_pattern = '/(' . $e . '[^' . $e . ']*(?:' . $e . $e . '[^' . $e . ']*)*' . $e . '|[^' . $d . ']*)' . $d . '/';
  preg_match_all($_csv_pattern, $_csv_line, $_csv_matches);
  $_csv_data = $_csv_matches[1];
 
  for ($_csv_i = 0; $_csv_i < count($_csv_data); $_csv_i++) {
    $_csv_data[$_csv_i] = preg_replace("/^" . $e . "(.*)" . $e . "$/s", "$1", $_csv_data[$_csv_i]);
    $_csv_data[$_csv_i] = str_replace($e . $e, $e, $_csv_data[$_csv_i]);
  }
 
  return empty ($_line) ? false : $_csv_data;
}
?>

 

加好就沒事了~

 

 

arrow
arrow
    文章標籤
    fgetcsv php php5 php7
    全站熱搜
    創作者介紹
    創作者 小攻城師 的頭像
    小攻城師

    小攻城師的戰場筆記

    小攻城師 發表在 痞客邦 留言(1) 人氣()