6

我有一串二进制数据,我需要它作为 IO 对象。所以我尝试了这个:

r, w = IO.pipe()
w << data

但它失败并出现此错误:

Encoding::UndefinedConversionError ("\xD0" from ASCII-8BIT to UTF-8)

为什么它首先尝试转换为 UTF-8?有没有办法将 IO::pipe 方法强制为二进制模式?

更多细节:

我正在尝试使用 Mongoid 驱动程序从 MongoDB 读取二进制数据(这是一个 Excel 文件),然后将其转换为 IO 对象,以便使用电子表格 gem 来读取它。Spreadsheet#open 需要文件路径或 IO 对象。

这是我的文件文档的外观:

class ImportedFile
    include Mongoid::Document

    field :file_name, type: String
    field :binary_content, type: Moped::BSON::Binary
end

这是我首先保存二进制数据的方式:

imported_file = ImportedFile.new
imported_file.file_name = uploaded_file.original_filename
imported_file.binary_content = Moped::BSON::Binary.new(:generic, uploaded_file.read)
imported_file.save

这就是我试图阅读它的方式(不起作用):

imported_file = ImportedFile.find(file_id)

r, w = IO.pipe()
w << imported_file.binary_content.data
book = Spreadsheet.open r
4

2 回答 2

5

您可能会使用 a StringIO

require 'stringio'

io = StringIO.new(binary_data)
book = Spreadsheet.open(io)
于 2013-07-13T19:14:42.373 回答
1

不要将raw StringIO用于二进制数据。我看到没有人StringIO在现实世界中测试过。

bin = ["d9a1a2"].pack("H*")
puts bin.encoding
puts bin[0].unpack("H*")
puts "----"

io = StringIO.new bin
puts io.string.encoding
puts io.string[0].unpack("H*")
puts "----"

io = StringIO.new
io << bin
puts io.string.encoding
puts io.string[0].unpack("H*")
io.string.force_encoding Encoding::BINARY
puts io.string.encoding
puts io.string[0].unpack("H*")
puts "----"

io = StringIO.new
io.binmode
io << bin
puts io.string.encoding
puts io.string[0].unpack("H*")
io.string.force_encoding Encoding::BINARY
puts io.string.encoding
puts io.string[0].unpack("H*")
puts "----"

io = StringIO.new
io.set_encoding Encoding::BINARY
io << bin
puts io.string.encoding
puts io.string[0].unpack("H*")
puts "----"

红宝石-2.3.3

ASCII-8BIT
d9
----
ASCII-8BIT
d9
----
UTF-8
d9a1
ASCII-8BIT
d9
----
ASCII-8BIT
d9
ASCII-8BIT
d9
----
ASCII-8BIT
d9
----

rbx-3.72

ASCII-8BIT
d9
----
ASCII-8BIT
d9
----
UTF-8
d9a1
ASCII-8BIT
d9
----
UTF-8
d9a1
ASCII-8BIT
d9
----
ASCII-8BIT
d9
----

jruby-9.1.7.0

ASCII-8BIT
d9
----
ASCII-8BIT
d9
----
UTF-8
d9a1
ASCII-8BIT
d9
----
UTF-8
d9a1
ASCII-8BIT
d9
----
ASCII-8BIT
d9
----
  1. 永远不要使用生StringIO的。
  2. 不要相信binmode。它不仅仅是 MRI 的存根。
  3. 使用io.set_encoding Encoding::BINARYio.string.force_encoding Encoding::BINARY
于 2017-02-26T17:32:25.077 回答