はじめに
Rubyにおけるタブ区切りのファイル(TSVファイル)から、BOM付きのCSVファイルへの変換方法です。
目次
0.完成コード
1.BOMを付けたCSVファイルの作成
2.TSVファイル内データの読み込み
3.CSVに1行づつ読んでは書いていく
4.プログラムを実行
0.完成コード
require 'csv'
# CSVファイルを作成し、bomを付ける。
File.write("meibo.csv", "\uFEFF")
# 'meibo2.txt'の情報を1行毎に読み込み、splitで配列にして、CSVファイルに1行ずつ入れていく。
CSV.open("meibo.csv", "a", force_quotes: true ) do |meibocsv|
File.foreach('meibo.txt') do |student|
meibocsv << student.chomp.split("\t", -1)
end
end
1.BOMを付けたCSVファイルの作成
BOM(Byte order mark)は、Unicodeの符号化形式で符号化したテキストの先頭に着ける数バイトのデータのことを言います。
ExcelはCSVファイルを開くときデフォルトでShift-JISで開こうとするため、UTF-8では文字化けを起こしてしまいます。その対処法として、UTF-8で出力する際にBOMを付けてあげることでExcelにUTF-8で書かれていると認識させて、文字化けを防ぐことができます。
以下のようにしてBOMを付けてます。
File.write("meibo.csv", "\uFEFF")
2.TSVファイル内データの読み込み
読み込むTSVファイルは以下。
john m 18
paul m 20
alice f 15
dabid m 17
jasmin f 17
タブ区切り形式のデータが書かれたmeibo.txtを読み込みますが、1行読み込んでは1行書き込むという手法をとりたいです。タブ区切りデータ1行をsplitで配列に変換した後、そのままCSVファイルに書き込んでいくようにします。
File.foreach('meibo.txt') do |student|
(CSVファイル) << student.chomp.split("\t", -1)
end
3.CSVに1行づつ読んでは書いていく
上のコードをCSV.openで囲えば、1行読み書きができます。
基本的に、タブ区切りファイルから、CSVファイルへ移すという場合は、1行ずつ処理していきます。なぜならば、仮に1000万行のような膨大なデータであっても、メモリがオーバーすることを防ぐためです。
CSV.open("meibo.csv", "a", force_quotes: true ) do |meibo_csv|
File.foreach('meibo.txt') do |student|
meibo_csv << student.chomp.split("\t", -1)
end
end
因みにsplitの第2引数(limit)に、-1を渡しています。
この第2引数の値はデフォルトでは0になっており、配列末尾の空文字列を取り除いてしまいます。
これではTSVに空のフィールドがあったときにうまく行きません。-1を渡してあげることで、解決することができます。
4.プログラムを実行
% ruby tsv_to_csv.rb
データが書き込まれたCSVファイルが生成される。
"john","m","18"
"paul","m","20"
"alice","f","15"
"dabid","m","17"
"jasmin","f","17"
カンマ区切りのCSVファイルに正しく変換されました。