我知道File
据说需要encoding: 'bom|utf-8'
,但是afaict没有相应的流。我的服务器正在获取一个包含一个具有bom的csv的zip文件。将csv保存为文件而不仅仅是使用CSV.new(Zip::InputStream::open(zip_file).get_next_entry.get_input_stream)
似乎很愚蠢,但是没有人可以检测并剥离字节顺序标记(bom),如果bom在那里,CSV
无法尝试解析标题。
我看到CSV.new
将encoding
作为一种选择,但是,至少在2.3.0中,它不承认bom
(ArgumentError: unknown encoding name - bom
)
看起来像处理BOM是在IO
中实现的 - 也许你可以将你的zip流包裹在IO
对象周围?
https://ruby-doc.org/core-2.3.1/IO.html#method-c-new-label-Open+Mode
既然你可以回卷流,那么答案就是得到第一个字符,看看它们是否是bom,如果它们是,消耗它们;否则,倒回流。
BYTE_ORDER_MARKS_LENGTHS =
{"\xEF".bytes.first => 2, "\xFE".bytes.first => 1, "\xFF".bytes.first => 1}
# checks if input_stream starts with a byte order mark and if so skips over it
def skip_bom(input_stream)
entry = BYTE_ORDER_MARKS_LENGTHS[input_stream.read(1).bytes.first]
if entry
input_stream.read(entry)
else
input_stream.rewind
end
end
我的情况类似,但我还需要删除额外的双引号:
Zip::File.open(zipfolder) do |zipfile|
zipfile.each do |zip_entry|
zip_entry.get_input_stream.each_line do |line|
line_without_bom_or_quotes = line.force_encoding('UTF-8').gsub('"', '')
row = CSV.parse_line(line_without_bom_or_quotes)
puts "DETAIL: #{row.inspect}"
end
end
end