前提
- Ruby 3.1.2
- ドキュメント
- 以下コードは
require 'csv'
している想定
読み込み
仕様としては、RFC4180 に準拠している
※ 例えば、フィールドをクォートで囲むことで、カンマを含んだ文字列を扱える等が定義されている
また、バリデーションは必要に応じて別途行うこと
例. raise MalformedCSVError if csv.first != CSV_HEADERS
ファイルから
一行ずつ
CSV.open(file_path, 'r').each do |row|
p row
end
# 結果
# [...]
# [...]
# ...
# => nil
CSV.foreach(file_path) do |row|
p row
end
# 結果
# [...]
# [...]
# ...
# => nil
# headers オプションに偽でない値を指定した場合、CSV::Table を返す
CSV.read(file_path, headers: true).each do |row|
p row
end
# 結果
# #<CSV::Row>
# #<CSV::Row>
# ...
# => #<CSV::Table>
# CSV.read(file_path, { headers: true, converters: :numeric, header_converters: :symbol }.merge(options)) と同じ
CSV.table(file_path).each do |row|
p row
end
# 結果
# #<CSV::Row>
# #<CSV::Row>
# ...
# => #<CSV::Table>
まとめて
CSV.open(file_path, 'r').to_a
# 結果
# [[...], [...], ...]
CSV.read(file_path)
# 結果
# [[...], [...], ...]
※ BOM 付き CSV の場合
-
BOM とは、符号化方式がUnicodeであることを判別するための印
- 具体的には、テキストの先頭につける数バイトのデータのこと
- Excelが絡むと起きるっぽい
- 別途 mode 指定することで、BOM を自動的に取り除く
CSV.open('test.csv', 'rb:BOM|UTF-8')
文字列から
# 準備
csv_text = <<EOS
id,first name,last name,age
1,taro,tanaka,20
2,jiro,suzuki,18
EOS
一行ずつ
CSV.parse(csv_text) do |row|
p row
end
# 結果
# ["id", "first name", "last name", "age"]
# ["1", "taro", "tanaka", "20"]
# ["2", "jiro", "suzuki", "18"]
# => 62
まとめて
CSV.parse(csv_text)
# 結果
# => [["id", "first name", "last name", "age"], ["1", "taro", "tanaka", "20"], ["2", "jiro", "suzuki", "18"]]
オプション
一覧のうち、よく使うものを抜粋
- ヘッダー
- 存在する場合は、
headers: true
-
~['カラム名']
で参照できるようになる - 変換する場合は、
header_converters: ~
- 変換例
- 文字列 → シンボル:
:symbol
- 独自設定:
->(h) { HEADER_MAPS[h] }
HEADER_MAPS = { 'a' => :a, 'b' => :b }
- 文字列 → シンボル:
- 変換例
- 存在する場合は、
- 区切り文字
- タブ区切りにしたい時は、
col_sep: "\t"
- タブ区切りにしたい時は、
- 文字コード
- 変換する例:
encoding: 'CP932:UTF-8'
- 変換する例:
- 不正CSV(RFC 4180 に違反)
- 具体的には、フィールド内にエスケープされていない二重引用符を含むケース
- パースする場合は、
liberal_parsing: true
- 例.
CSV.parse('a,b"c,d', liberal_parsing: true) => [["a", "b\"c", "d"]]
- 例.
- 解説記事
書き込み
※ 基本的にTSVで出力するようにしている
スプレッドシートに貼り付けて列分解する時に、列値にカンマ入っていると列がズレるため(列値にタブ入っていたら同じか。。スプレッドシート側の問題か)
ファイルへ
CSV.open("path/to/file.csv", "w") do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
※ BOM 付き CSV の場合
- 書き込み時にBOMを追加するオプションは
CSV.open
にはない- そもそも必要になることが少なそうではある
- なので、明示的にBOMを付与してあげる必要がある
文字列へ
csv_string = CSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
end
# 結果
# => "row,of,CSV,data\nanother,row\n"
オプション
よく使うものを抜粋
※ 読み込み
と同じ場合は省略
- ヘッダー
- 出力する場合は、
write_headers: true, headers: [...]
- 出力する場合は、