2010-02-05

Windows環境で作成したShift-JISのタブ区切りファイルをUTF-8でlinux上のrubyで扱う

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ファイル読み込みを行う際にcsvやtsvファイルを作ってもらって読み込むことが多々あると思います。
そんなファイルはたいていShift-JISになっていて、さらに最初の行がカラムの説明行になっていることもよくあると思います。

例えば、以下のようなファイルです。
test.tsv

日付 お名前 性別
2010/2/5 お試しするぞう 男
2010/2/5 試してみるわ 女


これをlinux上でrubyでUTF-8として読み込む方法です。

以下をなんとかします
・Shift-JISをUTF-8に変換する
・タブ区切りファイルを読み込む
・最初の行をなんとかする

FasterCSVを利用します。
インストールは
gem install fastercsv
でOK。

csvファイルでヘッダーがない場合は、以下のような感じで利用します。

require 'fastercsv'
FasterCSV.foreach('test.csv') { |row| p row}

csvを以下のような配列を得ることができます。

["2010/2/5", "お試しするぞう", "男"]
["2010/2/5", "試してみるわ", "女"]


で、今回の場合は以下のような感じにします。

require 'fastercsv'
FasterCSV.parse(NKF.nkf('-w -Lu',open('test.tsv').read),
:col_sep=>"\t",
:headers => true) {|row|
data = row.fields
p data
}

これで同じように
["2010/2/5", "お試しするぞう", "男"]
["2010/2/5", "試してみるわ", "女"]
となります。

・Shift-JISをUTF-8に変換する
 このために
 NKF.nkf('-w -Lu',open('test.tsv').read)
 でファイルの内容をUTF-8の文字列として取得します。
 ファイルを直接読むならば
  FasterCSV.foreach
 でよいのですが、文字列を扱うので
  FasterCSV.parse
 とします。

・タブ区切りファイルを読み込む
 :col_sep=>"\t"
 を指定すればOKです。

・最初の行をなんとかする
 :headers => true
 を指定することで先頭行をheaderとすることができます。
 ただこれだけだとcsvの値が配列ではなく

#<FasterCSV::Row "日付":"2010/2/5" "お名前":"お試しするぞう" "性別":"男">
#<FasterCSV::Row "日付":"2010/2/5" "お名前":"試してみるわ" "性別":"女">

 のようにFasterCSV::Rowオブジェクトになってしまいます。
 これだと各カラム内容を取得するためには
 row['日付']
 のようにする必要があります。
 ヘッダー情報が絶対変わらないのならばいいのですが、そうとも限らないとこれはこまるので
 data = row.fields
 で配列を取得しています。

前処理で文字変換と一行目除去をしておけばここまでしなくてもよいのですけどね。
コメントを投稿