LoginSignup
5

More than 5 years have passed since last update.

Ruby の CSV クラスで CSV::MalformedCSVError になった行を得る

Last updated at Posted at 2016-05-20

CSV クラスのインスタンスは、CSV データを持つ IO オブジェクトを @io というインスタンス変数で保持しています。
また CSV クラスのインスタンスはいくつかの IO メソッドを @io に委譲しています。

csv.rb
  ### IO and StringIO Delegation ###

  extend Forwardable
  def_delegators :@io, :binmode, :binmode?, :close, :close_read, :close_write,
                       :closed?, :eof, :eof?, :external_encoding, :fcntl,
                       :fileno, :flock, :flush, :fsync, :internal_encoding,
                       :ioctl, :isatty, :path, :pid, :pos, :pos=, :reopen,
                       :seek, :stat, :string, :sync, :sync=, :tell, :to_i,
                       :to_io, :truncate, :tty?

ということで、以下の様な感じで malformed な(物理)行を抽出する事ができました。

test.rb
require 'csv'
require 'tempfile'

Tempfile.create('malformed-csv') do |temp|
  temp.write(<<EOF)
id,name,value
"1","NAME","VALUE"
"2","NAME","VALUE"
"3",NAME"","VAL
UE"
EOF
  temp.flush

  processed_position = 0
  begin
    csv = CSV.open(temp.path)
    csv.each do |_|
      processed_position = csv.pos
    end
  rescue CSV::MalformedCSVError
    aborted_position = csv.pos
    io = csv.to_io
    io.seek(processed_position)
    p io.read(aborted_position - processed_position)
  end
end

__END__
"\"3\",NAME\"\",\"VAL\n"

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5