BigQuery に Shift-JIS ファイルのデータをロードするには?

2021.06.15

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、みかみです。

BigQuery にデータをロードする場合、データファイルのエンコーディングは UTF-8(または ISO-8859-1 )がサポートされています。

Shift-JIS(SJIS)ファイルだとロードできないのでしょうか?

やりたいこと

  • BigQuery に SJIS ファイルをロードした場合の挙動を確認したい
  • BigQuery に SJIS ファイルをロードするにはどうすればいいか知りたい

SJIS ファイルデータをそのままロードしてみる

以下の SJIS の CSV ファイルを準備しました。

col_num,col_alp,col_jp,col_timestamp
12345678,abcdefgh,日本語カタカナ,2021-06-15 00:00:00
99999999,ABCDEFGH,にほんごカタカナ,2021/06/15 23:59:59

file コマンドでも、エンコーディングが SJIS であることが確認できます。

mikami_yuki@cloudshell:~/sample/sjis (cm-da-mikami-yuki-258308)$ file sample_sjis.csv
sample_sjis.csv: Non-ISO extended-ASCII text

ためしに bq load コマンドで、SJIS のファイルをそのままロードしてみます。

mikami_yuki@cloudshell:~/sample/sjis (cm-da-mikami-yuki-258308)$ bq load --autodetect \
> --source_format=CSV \
> dataset_1.table_sjis \
> ./sample_sjis.csv
Upload complete.
Waiting on bqjob_r3b4bebe58e0f35d4_0000017a0e32a660_1 ... (1s) Current status: DONE

エラーにはならず、半角英数などのシングルバイト文字は正常にロードできましたが、マルチバイト文字の日本語は文字化けしてしまいました。。

mikami_yuki@cloudshell:~/sample/sjis (cm-da-mikami-yuki-258308)$ bq query "select col_jp from dataset_1.table_sjis"
Waiting on bqjob_r1b68b5b5432748a_0000017a0e374f00_1 ... (0s) Current status: DONE
+----------------+
|     col_jp     |
+----------------+
| ��–{��ƒJƒ^ƒJƒi |
| �ɂق?��Å        |
+----------------+

シェルスクリプトで UTF-8 に変換してからロード

以下の bash スクリプトを準備しました。

#!/bin/bash

iconv -f sjis -t utf8 sample_sjis.csv > sample_utf8.csv
bq load --autodetect --source_format=CSV dataset_1.table_utf8 ./sample_utf8.csv
bq query "select col_jp from dataset_1.table_utf8" > result_table_utf8.txt

iconv コマンドで UTF-8 に変換した新しいファイルを作成し、作成した UTF-8 のファイルを BigQuery にロードします。 ロード後には結果を確認するため、SJIS のファイルで文字化けしていた日本語カラムのデータを select してファイルに出力してみます。

mikami_yuki@cloudshell:~/sample/sjis (cm-da-mikami-yuki-258308)$ bash ./load_utf8.sh
Upload complete.
Waiting on bqjob_r45bd90bb2121d699_0000017a0e3e55f2_1 ... (1s) Current status: DONE
Waiting on bqjob_r7d034edc5790cb41_0000017a0e3e66a2_1 ... (0s) Current status: DONE

ロード結果の出力ファイルを確認すると

+----------------+
|     col_jp     |
+----------------+
| 日本語カタカナ   |
| にほんごカタカナ     |
+----------------+

問題なくロードできているようです。

念のため、BigQuery のテーブルデータも確認してみます。

マルチバイト文字(日本語)も文字化けすることなくテーブルに格納することができました。

pandas DataFrame に読み込んでからロード

ファイルのエンコーディング変換なしで、python プログラムでファイルデータを一度 pandas Dataframeに読み込んでから BigQuery にロードすることもできます。

以下の python コードを実行してみます。

import pandas as pd

file_path = './sample_sjis.csv'

df = pd.read_csv(file_path, encoding='shift-jis')
print(df)

dataset_id = 'dataset_1'
table_id = 'table_python'

df.to_gbq('{}.{}'.format(dataset_id, table_id), if_exists='replace')
mikami_yuki@cloudshell:~/sample/sjis (cm-da-mikami-yuki-258308)$ python3 load_sjis.py
    col_num   col_alp    col_jp        col_timestamp
0  12345678  abcdefgh   日本語カタカナ  2021-06-15 00:00:00
1  99999999  ABCDEFGH  にほんごカタカナ  2021/06/15 23:59:59

ファイルデータが文字化けせずにロードできたか、BigQuery のテーブルデータを確認してみます。

テーブルスキーマを指定しなかったので日時項目も STRING 型で格納されましたが、マルチバイト文字でも文字化けすることなく、正常にロードすることができました。

まとめ(所感)

BigQuery でサポートされていない SJIS ファイルのデータをロードしてもエラーにはなりませんが、日本語などのマルチバイト文字は文字化けしてしまいます。

ロードファイルを初めから UTF-8 で出力できればベストですが、SJIS ファイルのデータでも、シェルスクリプトや python コードで簡単にロードできました。

SJISファイルをロードする場合、ロード前にエンコーディングを UTF-8 に変換してしまうのも良いですが、ロード時にカラムの追加やデータフォーマット変換などの整形処理を行いたい場合は、pandas の DataFrame を使えば、そのまま BigQuery にロードできるので便利です。 なお、本エントリでは pandas.DataFrameto_gbq を使用しましたが、google-cloud-bigquery ライブラリにも DataFrame を BigQuery にロードするインターフェースがあるので、あわせてご確認ください。

参考