【问题标题】:Ruby: Binary String to IORuby:二进制字符串到 IO
【发布时间】:2013-07-13 19:02:23
【问题描述】:

我有一串二进制数据,我需要它作为 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

【问题讨论】:

    标签: ruby mongodb binary mongoid bson


    【解决方案1】:

    您可以为此使用StringIO:

    require 'stringio'
    
    io = StringIO.new(binary_data)
    book = Spreadsheet.open(io)
    

    【讨论】:

    • 工作就像一个魅力!谢谢!
    【解决方案2】:

    不要将 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 "----"
    

    ruby-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::BINARY 或io.string.force_encoding Encoding::BINARY。

    【讨论】:

    • io.set_encoding Encoding::BINARY 仍然是 MRI 3.0.1 的一个很好的解决方案
    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 2016-02-26
    • 1970-01-01
    • 2015-11-21
    • 2012-08-27
    • 2023-03-27
    相关资源
    最近更新 更多