Google Code Prettify

2022年9月6日 星期二

【筆記】PHP + PostgreSQL 將資料寫入檔案 - CSV 格式

環境

  • Ubuntu 18.04
  • PHP 7.4
  • PostgreSQL 10.22

使用情境

    欲將 PostgreSQL 中的資料寫入檔案,並且希望使用 CSV 格式。其中部分字串資料包含 , 字元。

基本函數 

    使用 pg_copy_to() 函數來模擬 PostgreSQL CLI 中的 COPY 語法(使用 pg_query() 等函數無法使用 COPY)。

  1. $db = pg_connect($connection_string);
  2. $sql = "SELECT col1, col2 FROM table WHERE conds;";
  3. # 第二個參數在 () 放入欲複製的語法,第三個參數為分隔符號
  4. $data = pg_copy_to($db, "($sql)", ','); # 回傳資料為 Array

   然而 pg_copy_to() 無法設定分隔符號,也無法使用 PostgreSQL 語法的 CSV HEADER 等後綴詞,只會將反斜線(\)、逗號(,)及換行符號用反斜線(\)跳脫。分別會變成\\\,\r\n。這些跳脫格式不符合大部分程式讀取 CSV 檔的規則,常常造成一些欄位錯誤的問題。因此最好將這些資料轉換成更通用的格式。

正規語言做字串處理

    使用以下方式將字串手動轉換成 CSV 適用的格式,主要是將含有跳脫字元的欄位用雙引號包起來,並且將跳脫字元處理掉,也不能忘記雙引號的處理。

  1. # 一共進行四次轉換
  2. # 第一次將雙引號轉換成兩個雙引號以跳脫
  3. # 第二次轉換將含有反斜線或兩個雙引號的欄位用雙引號包住
  4. # 第三次轉換將 \r\n 取代為換行
  5. # 第四次將跳脫用的反斜線去除
  6. $pattern = array('/\\"/','/((?:\\\\.|[^\\\\,])*(?:\\\\.|\\"\\")[^\\\\,]*)/','/\\\\r\\\\n/','/\\\\(.)/');
  7. $replace = array('""','"$1"', "\n", '$1');
  8. $data = preg_replace($pattern, $data); # preg_replace 可傳入 Array,回傳 Array

寫入檔案

   將轉換後的結果寫入檔案。

  1. $path = '/path/to/file.csv';
  2. # 由於無法使用 HEADER 後綴,必須自己加上標頭
  3. $title = 'col1,col2';
  4. $fp = fopen($dir.'release_list_survey.csv',"w");
  5. # 若資料中含有非 ASCII 字元,且使用者有用 EXCEL 開啟檔案的需求,開頭必須加入 BOM 才會自動使用 UTF-8 編碼
  6. fwrite($fp,"\xEF\xBB\xBF");
  7. fwrite($fp,$title."\n");
  8. # 目前我使用的版本,pg_copy() 的結果本身就含有換行,因此 implode() 參數代入空字串,依版本可能需要改成 "\n"
  9. fwrite($fp,implode("", $data));
  10. fclose($fp);

    以上是今天的筆記。

沒有留言:

張貼留言