多言語文字を文字化けせずにCSV形式で出力するには?
仕事で多言語サイト作成でハマった所を一つ。
内容は、多言語表示した表(文字)をCSVでダウンロード出力する。といった内容だったのですが。。。
時系列で書いていきます。
が、気の早いあなたには、先に結論を。
タブ区切りのUTF16LE(リトルエンディアン):Bom付で出力してあげればOKです。
これでcsvファイルのダブルクリックでちゃんと文字化けせずに読み込めます。
ただ、検証環境は要件からWindows + Excel2000です。
新しいEccelやMacOfficeは検証していません。
というか、検証してくださるとありがたい><
さて、多言語文字を出力する場合、当然文字コードはユニコード系で書き出さないといけないです。
(ここで言うユニコード系はUTF-8orUTF-16)
このCSV出力で色々とはまりどころが。。。
カンマ区切り
カンマ区切りCSVのダブルクリックで読み込む場合、Excelが読込む文字コードは「Shift-JIS」なので文字化けでNGでした。第一段階の答え『カンマ区切りはボツ』
ここで、「いやいや、UTF-8でも開けるよ!」と言う方もいると思いますが、ポイントはダブルクリック。
確かにExcelを起動して『ファイルを開く』とUTF-8でも読み込めます。
当初クライアントにその方法で使ってもらうおうかと思いました・・・が、確実にそれは嫌だと言われそうなのでもう少し考えてみることに。
逆にExcelからテキストファイルをUnicodeで出力する場合、タブ区切りだと言うところに気がつきました。
ということはタブ区切りに解決の糸口が・・・
タブ区切り
各文字コードでタブ区切りCSVファイルを用意してExcelに読み込んでみます。 色々試したところ、メモ帳での保存時にファイル形式をUnicode(UTF-16LM)で保存。拡張子をcsvに変更。 するとCSVファイルは、ダブルクリックでExcelで正常に表示できることを確認しました。第二段階の答え『タブ区切りならいけそう!』
で、実際にサーバサイド(その時はC#)でUTF-16出力し、ダウンロードしたCSVファイルをダブルクリック!
あれ、ダメ?
いや、大丈夫な時もある???
なぜ??
Bom(Byte Order Mark)
バイナリエディッタなどで色々出力ファイルを調べていると答えが見つかりました。 不安定に見えた挙動は、メモ帳のせいでした。 メモ帳はUTF-16のファイルを開く時、Bomの有/無に関わらず読み込むことが出来る。 逆に保存時は必ずBomを付与するのです。以前ここでメモ帳の挙動を書いてますが、ExcelはリトルエンディアンのBom付UTF-16じゃないと開けないということが分かりました。
Byte Order MarkUTF-16においてはビット列の並びを表す印の事で、ファイルの先頭に識別用のビットをつけることで区別する。- FFFE:リトルエンディアン
- FEFF:ビッグエンディアン
この印をつける形式をBOM付き、つけない場合はBOM無しということになる。
つまり、ダウンロードしたファイルの確認のため一度開いて保存したCSVファイルの場合はBomが付与されてOK。
そのままダブルクリックした場合は、NGだったということです。
見た目には全く違わないのでなかなか気がつきませんでした・・・
さっそくファイル生成時にBom付でファイルを出力すると無事ダブルクリックで開くことが出来ました。
つまり
- 区切り文字はタブ(いわゆるTSV)
- 文字コードはUTF-16
- Bomを付ける。種類はLE(リトルエンディアン)
ここで書いたC#のCSV出力は一応その成果を反映していて、タブ区切りでの出力は多言語対応しています。
PHPはこちら → PHPで多言語文字のCSVファイル出力
参考この問題を解決する際、下記サイトが非常に役に立ちました。 Excel 2003 の CSV と 文字エンコーディング の関係