如何将.png文件的数据嵌入Ruby文件中?

如何将.png文件的数据嵌入Ruby文件中?,ruby,image,Ruby,Image,我的问题是关于Ruby源文件以及在其中存储二进制数据的能力 我知道在Ruby文件中\uuuuuuuuuuuuuuu\uuuuuuu之后,我可以将我想要的任何数据放在那里,文件仍然可以正常工作 然后我可以通过数据常量加载它 给定一个文件“foobar.png”,我如何将这些数据放入一个文件中,在\uuuu END\uuuu注释后存储该文件,然后再次加载它,这样我就有了一个“功能性”图像 我的想法是创建一个Ruby文件,它向用户提供HTML(启动时默认使用Webrick),并具有一些小图像 稍后,我

我的问题是关于Ruby源文件以及在其中存储二进制数据的能力

我知道在Ruby文件中
\uuuuuuuuuuuuuuu\uuuuuuu
之后,我可以将我想要的任何数据放在那里,文件仍然可以正常工作

然后我可以通过
数据
常量加载它

给定一个文件“foobar.png”,我如何将这些数据放入一个文件中,在
\uuuu END\uuuu
注释后存储该文件,然后再次加载它,这样我就有了一个“功能性”图像

我的想法是创建一个Ruby文件,它向用户提供HTML(启动时默认使用Webrick),并具有一些小图像


稍后,我希望最终在该文件中存储多个.png文件,但现在我只想了解如何读取应为.png文件的数据流。

我想UNIX读取二进制数据的方法是。有一种方法可以顺利地用于此类数据

一般用法代码示例:

require 'base64'

encode = Base64.encode64(File.read('/path/to/my_awesome_picture.jpg') # this will convert picture to ASCII text
decode = Base64.decode64(File.write('/path/to/new_awesome_picture.jpg', encode)) # This will convert

注意:实际上没有测试代码,但应该可以工作。

因为Ruby文件是以文本编码的,所以不能将数据包含为二进制blob,所以必须以某种方式对其进行编码。最简单的方法是合并格式。执行类似于在将PNG名称映射到Base64数据之后放置JSON对象的操作。因此:

require "json"
require "base64"

f = File.open("thiscamefromthescript.png", "wb")

f.write(Base64.decode64(JSON.parse(DATA.read)['some_png']))

__END__
{
  "some_png" : "BASE64ENCODEDIMGAGEHERE"
}

您可以非常简单地做到这一点,至少对于一个文件,尽管我不确定是否推荐它。源文件的
数据
部分的内容(
\uuuuu END\uuuu
之后的位)不需要是文本,它们可以是任何二进制数据,您可以使用将其放置到位

DATA
常量只是一个对象,因此您可以对其调用
read
,以获取字符串中的数据

下面是一个使用Sinatra为图像提供服务的示例。(在某些方面使用Sinatra会使这变得更复杂,因为在经典模式下,Sinatra会查看数据段本身以获取内联模板,这就是本示例使用模块化样式的原因)

然后,您可以运行
ruby combined.rb
,Sinatra服务器将为您的映像提供服务,以满足对其根目录的任何请求

我认为Java for Linux的早期版本是以自解压二进制文件的形式发布的,它使用了与此类似的技术—它使用了一个连接到压缩归档文件的shell脚本,该脚本检测到同一文件中压缩内容的开头,并解压缩并写出这些文件

以这种方式合并多个文件会很棘手。您可能需要一些分隔符来分隔它们,因为您处理的是二进制数据,所以需要确保分隔符不会出现在实际数据中。我认为最简单的解决方案是对它们进行base64编码,并在数据部分使用一些数据格式,您的代码可以对其进行解析和解码


但我怀疑这是否是正确的方式。如果您想让分发脚本变得更容易,那么更好的选择可能是将所有内容打包到包含代码和图像的gem中。

虽然这是可行的,但这是一个非常糟糕的主意。.png文件的等效表示形式在文本文件中要大得多,这就是Ruby脚本。此外,您必须修改源代码才能修改图像。相反,将源代码和数据拆分,不要将它们合并到单独的Ruby脚本和单独的PNG文件中,并根据需要从磁盘加载它们。这将非常快速,并且不需要编辑代码来添加/删除图像。替代方法是重定向浏览器,将适当的文件作为“图像”(HTTPd)服务器提供的静态图像加载,或将其作为blob或数据库中的文件名和磁盘上的图像存储在数据库中,等等,除了将编码数据存储在文件中,我什么都愿意做。
require 'sinatra/base'

class App < Sinatra::Base

  set :image, DATA.read 

  get '/' do
    headers['Content-type'] = 'image/png'
    settings.image
  end

end

App.run!

# make sure there's a newline after __END__
# but only one so you don't add any more data at the
# start of your image file
__END__
cat source.rb image.png > combined.rb