在ruby中从zip流中剥离字节顺序标记

在ruby中从zip流中剥离字节顺序标记,ruby,csv,encoding,inputstream,Ruby,Csv,Encoding,Inputstream,我知道该文件应该采用编码方式:“bom | utf-8”,但在afaict中,流并没有等价的编码。我的服务器得到一个zip文件,其中包含一个包含bom的csv。与仅使用csv.newZip::InputStream::openzip_file.get_next_entry.get_input_stream相比,将csv保存为文件似乎很愚蠢,但是,如果存在bom,则没有一个csv可以检测并去除字节顺序标记bom,并且csv无法尝试解析标题 我看到CSV.new将编码作为一个选项,但是,至少在2.3

我知道该文件应该采用编码方式:“bom | utf-8”,但在afaict中,流并没有等价的编码。我的服务器得到一个zip文件,其中包含一个包含bom的csv。与仅使用csv.newZip::InputStream::openzip_file.get_next_entry.get_input_stream相比,将csv保存为文件似乎很愚蠢,但是,如果存在bom,则没有一个csv可以检测并去除字节顺序标记bom,并且csv无法尝试解析标题


我看到CSV.new将编码作为一个选项,但是,至少在2.3.0中,它不识别bom参数错误:未知编码名称-bom

因为您可以回放流,答案是获取第一个字符,查看它们是否是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

看起来处理BOM是在IO中实现的-也许您可以围绕IO对象包装您的zip流


我的情况与此类似,但我还需要删除额外的双引号:

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

它应该是BOM | UTF-8,而不仅仅是BOM。当然,我尝试过这一点以及所有不同的排列。Fetching Encoding.name_列表显示没有与BOM大小写不变量或子字符串类似的编码。我很好奇BOM编码的来源。谢谢!唉,IOnew不接受Zip::InputStream作为fd,但这至少解释了BOM的定义位置!>io=io.newstream,'r:BOM | UTF-8'类型错误:没有将Zip::InputStream隐式转换为整数如何将io传递到Zip流?基本上,您希望首先通过IO运行它来处理编码,然后将其传递到zip流以解压,最后但并非最不重要的是使用CSV库CSV.newZip::InputStream::openIO.openzip_文件“r:BOM | UTF-8”。get_next_entry.get_input_stream我相信zip文件没有BOM,但zip中的文件有;因此,这将不起作用,并且实际上可能会得到错误警报。因此,在这种情况下,您可能会将来自zip的流包装到另一个IO流中?stream_with_bom=Zip::InputStream::openzip_file.get_next_entry.get_input_stream然后CSV.new IO.openstream_with_bom,'r:bom | UTF-8'如果你能上传一个示例文件,我可以尝试实际运行代码