我想用ruby的默认CSV库编写一个CSV,以便使用MySQL的快速导入LOAD DATA INFILE。
目前,当我为某个字段输入nil时,它被写为...;;...
,而我希望它为...;\N;...
(大写N表示NULL,不要与\ n换行符混淆)。
CSV.open(product_updates_file_name, "wb", {col_sep: ";", headers: false, force_quotes: false}) do |product_csv|
product_csv << ["foo", nil, "bar"]
end
它当前导致十进制字段在数据库中加载为0.00而不是NULL。
我知道,之后我可以将它设置为NULL,但是有数百万行和几列受到影响,所以我强烈建议按照MySQL的预期编写CSV:
答案 0 :(得分:0)
尝试覆盖nil
的{{1}}方法,如下所示:
to_s
使用class << nil
def to_s
"my nil placeholder text"
end
end
的所有代码都将使用此实现作为值nil。
答案 1 :(得分:0)
您可以修改CSV方法:
require 'csv'
class Array
alias :old_to_csv :to_csv
#Extend to_csv for usage like ["foo", nil, "bar"].to_csv( :col_sep => ";")
def to_csv(options)
self.map{|s| s.nil? ? '\N' : s }.old_to_csv
end
end
class CSV
alias :old_push :<<
def <<(data)
case data
when Array
old_push data.map{|s| s.nil? ? '\N' : s }
else
old_push data
end
end
end
#Testcode:
puts ["foo", nil, "bar"].to_csv( :col_sep => ";") #--> [["foo", "\\N", "bar"]]
CSV.open('test.csv', "wb",
{col_sep: ";", headers: false, force_quotes: false }
) do |product_csv|
product_csv << ["foo", nil, "bar"]
end
#-> Creates test.csv with 'foo;\N;bar'
仅在插入数组时才有效。如果插入其他内容,则必须修改逻辑。
注: 我的第一个想法是使用转换器。但它仅用于解析csv,而不是用于编写。
CSV::Converters[:nil_N] = lambda{|s|
s.nil? ? '\N' : s
}
p CSV.parse('foo;;bar', :col_sep => ";", :converters => :nil_N)
#-> [["foo", "\\N", "bar"]]
也许其他人知道使用转换器构建csv文件的方法。