Help us understand the problem. What is going on with this article?

CSV.open で Encoding::UndefinedConversionError になる場合

More than 5 years have passed since last update.

Ruby 標準添付ライブラリの CSV で Windows-31J (Shift_JIS でも良いけど) な CSV を作っていたのだけれども、特定の文字が含まれていると Encoding::UndefinedConversionError になってしまう。

irb(main):011:0> CSV.open(File.join('/var/tmp/hoge.csv'), 'w', encoding: 'Windows-31J') do |csv|
irb(main):012:1*   csv << %w( d é f )
irb(main):013:1> end
Encoding::UndefinedConversionError: U+00E9 from UTF-8 to Windows-31J

最初は気楽に undef とか replace とか指定すれば良いんでしょ、とか思っていたんだけど。

irb(main):014:0> CSV.open(File.join('/var/tmp/hoge.csv'), 'w', encoding: 'Windows-31J', undef: :replace, replace: '*') do |csv|
irb(main):015:1*   csv << %w( d é f )
irb(main):016:1> end
ArgumentError: Unknown options:  undef, replace.

CSV.open に undef も replace も渡せない。
(話の流れで省略してるけど invalid も同じように渡せない)

実際に例外出しているのは CSV.new で、 CSV.new には決まったオプションしか渡せない。

書き出しの手間を考えると CSV ライブラリは使いたい、でも undef, replace 使いたい。
でも CSV.new には undef とか渡せない、でも文字コード変換して CSV 書き出したい。
とかぐるぐるしてたんだけれども。

実際に CSV.open が何をやっているかを参考にしつつ。
File.open して、それを CSV.new に渡すことにした。

irb(main):017:0> File.open(File.join('/var/tmp/hoge.csv'), 'w', encoding: 'Windows-31J', undef: :replace, replace: '*') do |file|
irb(main):018:1*   csv = CSV.new(file, encoding: 'Windows-31J')
irb(main):019:1>   begin
irb(main):020:2*     csv << %w( d é f )
irb(main):021:2>   ensure
irb(main):022:2*     csv.close
irb(main):023:2>   end
irb(main):024:1> end
=> <#CSV io_type:File io_path:"/var/tmp/hoge.csv" encoding:Windows-31J lineno:1 col_sep:"," row_sep:"\n" quote_char:"\"">

これで、例外にならない。

$ cat /var/tmp/hoge.csv
d,*,f

指定の通りに replace されてる。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away