Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
790 views
in Technique[技术] by (71.8m points)

Ruby CSV doesn't find file headers if first line is followed by an empty one

I have encountered an odd issue where my script wouldn't work on some CSV files. Problem is the following, I need to access the column names (file headers) to properly process the file. I've been using the following (test) code to list the headers :

CSV file = CSV.read(argument, :headers => true)
if file.headers() == nil
    puts "According to the doc : Headers will not be used"
elsif file.headers() == true
    puts "According to the doc : Headers will be used, but not read yet"
else
    puts "Headers were read, this is an array : #{file.headers.to_s}"
end

Now, applied to the first csv :

key,fr
edit,éditer
close,Fermer

I get :

Headers were read, this is an array : ["key", "fr"]

But, if I know add an empty line between the headers and the content itself, like so :

key,fr

edit,éditer
close,Fermer

It doesn't work anymore :

Headers were read, this is an array : []

This baffles me. Is this expected behavior ? Is there anything I can do about it ? I've been reading the ruby CSV doc but cannot find anything. Could it be some csv file specs I don't know about ? Tested on ruby 1.9.3 and 2.1.1

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Add the option :skip_blanks => true when you are reading the CSV file.

file = CSV.read(path, :headers => true,:skip_blanks => true)

This option :skip_blanks => true, will skip all such blank lines if any present like you are having, and you will get the normal output.

Here is my try for the same :

require 'csv'

content = <<_
key,fr

edit,éditer
close,Fermer
_

File.write('test',content)

file = CSV.read('test', :headers => true,:skip_blanks => true)
if file.headers() == nil
    puts "According to the doc : Headers will not be used"
elsif file.headers() == true
    puts "According to the doc : Headers will be used, but not read yet"
else
    puts "Headers were read, this is an array : #{file.headers.to_s}"
end
# >> Headers were read, this is an array : ["key", "fr"]

Working correctly as you said, and I also agreed with you, below one :

require 'csv'

content = <<_
key,fr
edit,éditer
close,Fermer
_

File.write('test',content)

file = CSV.read('test', :headers => true)
file.headers # => ["key", "fr"]
file.to_a # => [["key", "fr"], ["edit", "éditer"], ["close", "Fermer"]]

When you set :headers => true, the first row of the CSV data, you have will be tread as header. With this definition in mind, The above goes well. But the below one contradicts :

require 'csv'

File.write('test',content)

file = CSV.read('test', :headers => true)
file.headers # => ["key", "fr"]
file.to_a # => [["key", "fr"], ["edit", "éditer"], ["close", "Fermer"]]

content = <<_
key,fr

edit,éditer
close,Fermer
_

File.write('test1',content)

file = CSV.read('test1', :headers => true)
file.headers # => []  # <~~~~~~~~~~~ Is this a bug ?
file.to_a # => [[], [], ["edit", "éditer"], ["close", "Fermer"]]

file.headers gives an empty array [], as you can see that in the 0th index of the output of file.to_a is also an empty array([]). But it seems to a bug. Thus I raised the issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...