# 注意
内容がグダグダなので、以下に書き直しました。
Ruby文字エンコードに悩まされ、直接指定やnkfによる推測などを試した
http://qiita.com/rojiuratech/items/9d40cb294eb08f2204ac
概要
RubyでUTF-8ではないCSVを読み込み、取り扱う話。
直接読み込もうとしたらダメだったが。一旦変換掛けててから扱えば
すんなりと通った。
環境
- ruby 2.2.3
CSVライブラリで、UTF-8でないCSVが読み込めない。
他部門はWindowsPCを使っており、MS-ExcelでCSVファイルを保存しようとすると、Shift_JISで保存されてしまいます。
ところが、Rubyに最初からあるCSVクラスで、UTF-8以外のファイルを開こうとすると・・・。
/ruby/2.2.0/csv.rb:2007:in `=~': invalid byte sequence in UTF-8 (ArgumentError)
rom read_csv.rb:3:in `<main>'
などというエラーが発生。
require "csv"
data = CSV.read(ARGV[0])
data.each do |str|
p str.toutf8
end
UTF-8的に正しくないバイトシーケンスが混じっていて、そこでコケたようです。
この辺りは下記リンクでも述べられています。
sonnets:blog
Ruby の invalid byte sequence in UTF-8 例外を encode("UTF-8", "UTF-8") で回避するのはおかしいよ、という話
。
過去やっていた、ひどい対応
CSVファイルをエクセルで読み込んで、それをxlsx形式で保存し、
roo(ruby上でスプレッドシートを扱うGem)を使って読み込みインポート・・・。などの、やむをえないけど意識低いことをやってた。
先日のkawasaki.rbで、文字コードの変換話が出た
パーフェクトRubyで、文字列の文字コードを変換して、同じ値か比較する・・・。みたいな話が出てきた。
なら、文字エンコードを変換して与えれば良いのでは?!
方針
読み込むCSVファイルは、ただのテキストファイルとして読み込む。
この時、文字コードをUTF-8にして読む。
UTF-8に変換後のデータを、CSVクラスで扱う。
追記! 正しくは File.read
です。
# 使用するライブラリを読み込む
require 'kconv'
require 'csv'
#読み込み対象ファイルのパスを受け取る
read_file = ARGV[0]
# 読み込み対象ファイル
raw_str = ""
#読み込み対象のファイルを、一度に読み込む
raw_str = File.read(read_file)
# raw_str = File.open(read_file)
# 読み込んだものを配列化
mod_str = CSV.parse(raw_str)
#1行ずつ表示する
i = 0
mod_str.each do |str|
p i
p str
i = i + 1
end
ためしによみこむファイル
品名,種類,値段
棍棒,武器,60
薬草,drug,10
毒草,drug,1
,(空欄),2000
いつもの,何か,45くらい
,,
$ ruby read_sjis.rb fake_euc.csv
0
["品名", "種類", "値段"]
1
["棍棒", "武器", "60"]
2
["薬草", "drug", "10"]
3
["毒草", "drug", "1"]
4
[nil, "(空欄)", "2000"]
5
["いつもの", "何か", "45くらい"]
6
[nil, nil, nil]
このやり方が真価を発揮するのは・・・
セル内改行を含むケース。だと思う。