Rubyでのファイル形式の変換まとめ（TSV, CSV, JSON)

###ファイル形式の種類
データには様々な形式がありますが、入力のファイル形式と違うファイル形式で出力したいことがあると思います。今回は、以下の3つのファイル形式を扱い、Ruby上で変換する方法をまとめました。

①TSV (Tab Separated Values)・・・各項目の間がタブで区切られたテキストデータ。拡張子はtxtかtsv。

```people.tsv
alice  f  20
bob    m  19
conner m  34
david  m  23
elena  f  24
```
②CSV (Comma Separated Values)・・・各項目の間がカンマ(,)で区切られたテキストデータ。拡張子はtxtかcsv。

```people.csv
"alice","f",20
"bob","m",19
"conner","m",34
"david","m",23
"elena","f",24
```

③JSON (JavaScript Object Notation)・・・ Javascriptで組み込まれているオブジェクトというデータ記述をベースとしたデータ。Rubyでいうハッシュのようなキーと値を持つ。拡張子はtxtかjson。

```people.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
```ruby
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


```ruby

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行目で読み込みます。
最後の行に注目してください。

```ruby

File.write('meibo.json', JSON.dump(people))
```
jsonモジュールには、rubyハッシュをjsonに変換するdumpというメソッドが含まれています。そのため、meibo.txtをrubyでハッシュ化すれば（ここではpeopleという変数に格納）、jsonとして出力することができます。

```ruby

people << {"name" => cols[0], "gender" => cols[1], "age" => cols[2]}
```
rubyのハッシュとjsonはキーを持ちます。今回のタブ区切りファイルにはキーが含まれていないので、明示的に作成しています。


##CSVの変換

###CSV→TSV
```ruby
require 'csv'

File.open('meibo.txt', 'w') do |f|
  CSV.foreach('people.csv') {|line|
      f << line.join("\t")
      f << "\n"
  }
end
```
CSV.foreachメソッドは、各行を配列として１行ずつ出力します。（File.foreachは文字列として出力）
joinメソッドを使って、配列の要素をタブ区切りの一つの文字列として書き込みます。

###CSV→JSON
```ruby
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
```ruby
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
```ruby
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でファイルを開き、１要素ずつを配列化してfに加えてます。