###ファイル形式の種類
データには様々な形式がありますが、入力のファイル形式と違うファイル形式で出力したいことがあると思います。今回は、以下の3つのファイル形式を扱い、Ruby上で変換する方法をまとめました。
①TSV (Tab Separated Values)・・・各項目の間がタブで区切られたテキストデータ。拡張子はtxtかtsv。
alice f 20
bob m 19
conner m 34
david m 23
elena f 24
②CSV (Comma Separated Values)・・・各項目の間がカンマ(,)で区切られたテキストデータ。拡張子はtxtかcsv。
"alice","f",20
"bob","m",19
"conner","m",34
"david","m",23
"elena","f",24
③JSON (JavaScript Object Notation)・・・ Javascriptで組み込まれているオブジェクトというデータ記述をベースとしたデータ。Rubyでいうハッシュのようなキーと値を持つ。拡張子はtxtかjson。
[{"name":"alice","gender":"f","age":"20"},
{"name":"bob","gender":"m","age":"19"},
{"name":"conner","gender":"m","age":"34"},
{"name":"david","gender":"m","age":"23"},
{"name":"elena","gender":"f","age":"24"}]
これらを互いに変換していきたいと思います。
##TSVの変換
###TSV→CSV
require 'csv'
CSV.open('people.csv','w', :force_quotes => true) do |people|
File.foreach("people.txt") {|line| people << line.chomp.split(/\t/)}
end
rubyでcsvを使用するには、csvモジュールを1行目で読み込む必要があります。
CSVの書き込みは、CSV.open('新しいファイル名', 'w')とします。
:force_quotesは、全ての文字列をダブルクオーテーションでくくるようににするオプションです。
foreachメソッドは、ブロックと一緒に使うことで、引数にとったファイルを1行ごとに文字列として抽出することができます。ここでは、people.txtが行ごとにlineという変数に置き換わり、ブロック内の処理が行われます。lineは文字列なので、chompで改行を削除、split(/\t/)でタブを要素の区切りとみなして、文字列を配列に変えます。
この配列を、peopleに追加しています(<<メソッド)。peopleは、CSV.openのブロック変数で、これに配列を追加するとcsvファイルの内容を書き換えることができます。
###TSV→JSON
require 'json'
people = []
File.foreach('meibo.txt') {|line|
cols = line.chomp.split("\t")
people << {"name" => cols[0], "gender" => cols[1], "age" => cols[2]}
}
File.write('meibo3.json', JSON.dump(people))
rubyでjsonを使用するには、jsonモジュールを1行目で読み込みます。
最後の行に注目してください。
File.write('meibo.json', JSON.dump(people))
jsonモジュールには、rubyハッシュをjsonに変換するdumpというメソッドが含まれています。そのため、meibo.txtをrubyでハッシュ化すれば(ここではpeopleという変数に格納)、jsonとして出力することができます。
people << {"name" => cols[0], "gender" => cols[1], "age" => cols[2]}
rubyのハッシュとjsonはキーを持ちます。今回のタブ区切りファイルにはキーが含まれていないので、明示的に作成しています。
##CSVの変換
###CSV→TSV
require 'csv'
File.open('meibo.txt', 'w') do |f|
CSV.foreach('people.csv') {|line|
f << line.join("\t")
f << "\n"
}
end
CSV.foreachメソッドは、各行を配列として1行ずつ出力します。(File.foreachは文字列として出力)
joinメソッドを使って、配列の要素をタブ区切りの一つの文字列として書き込みます。
###CSV→JSON
require 'csv'
require 'json'
people = []
CSV.foreach('people.csv') {|line|
people << {"name" => line[0], "gender" => line[1], "age" => line[2]}
}
File.write('people.json', JSON.dump(people))
##JSONの変換
###JSON→TSV
require 'json'
File.open('meibo.txt', 'w') do |f|
File.open('meibo.json') do |json|
people = JSON.load(json)
people.each do |person|
f << [person["name"], person["gender"], person["age"]].join("\t")
f << "\n"
end
end
end
jsonモジュールのloadメソッドは、JSON形式の文字列を Rubyオブジェクトとして返します。ここでは、peopleという変数にそれを代入し、eachメソッドで処理することで各要素を抽出しています。
###JSON→CSV
require 'csv'
require 'json'
CSV.open('meibo.csv', 'w', :force_quotes => true) do |f|
File.open('meibo.json') do |json|
people = JSON.load(json)
people.each do |person|
f << [person["name"], person["gender"], person["age"]]
end
end
end
CSV.openで開いたファイル(変数f)に配列を突っ込むといい感じにcsvファイルとして扱ってくれます。
JSON.loadでファイルを開き、1要素ずつを配列化してfに加えてます。