【问题标题】:Is there a way to check if a Ruby variable contains binary data?有没有办法检查 Ruby 变量是否包含二进制数据?
【发布时间】:2017-10-01 18:09:26
【问题描述】:

我使用的是 Ruby 2.4 和 Rails 5。我在一个名为“content”的变量中有文件内容。内容可能包含来自诸如 PDF 文件、Word 文件或 HTML 文件之类的数据。有什么方法可以判断变量是否包含二进制数据?最后,我想知道这是 PDf、Microsoft Office 还是其他类型的 OpenOffice 文件。这个答案——Rails: possible to check if a string is binary?——建议我可以检查变量的编码

content.encoding

它会产生

ASCII-8BIT

然而,在二进制数据的情况下,我注意到有些情况下,存储在变量中的 HTML 内容也可以返回“ASCII-8BIT”作为 content.encoding,因此使用“content.encoding”不是告诉我是否有二进制数据的万无一失的方法。这种方式是否存在,如果存在,是什么?

【问题讨论】:

  • 鉴于您的要求,您似乎需要对内容进行一些分析。我会提取前 n 个字节并根据您的标准 ASCII 代码检查它们。如果您遇到的许多字符不是 ASCII,那么您的内容很可能是二进制的。似乎卡方检验可能很合适。为什么不能访问实际的文件对象?
  • 我正在从没有关于文件的其他信息的数据库中访问内容。有时有一个文件名,但扩展名对于确定文件/内容类型是不可靠的。
  • 等等,文件的内容在数据库里吗?
  • 我您真正的问题不是关于二进制数据本身,而是关于确定数据的文件类型,我建议您查看ruby-filemagic gem,它将为您提供更多信息可靠。
  • @Dave 根据 github.com/blackwinter/ruby-filemagic 的 gem 文档,它可以使用缓冲区,因此您不需要向文件写入任何内容。只需将前 N 个字节读入内存并将其传递给 gem。

标签: ruby-on-rails ruby encoding binary ms-office


【解决方案1】:

如果您真正的问题不是关于二进制数据本身,而是关于确定数据的文件类型,我建议您查看ruby-filemagic gem,它将为您提供这些信息更可靠。 gem 是 libmagic 库的一个简单包装器,它是类 unix 系统上的标准库。该库通过扫描文件的内容并将其与各种文件类型中的一组已知“神奇”模式进行匹配来工作。

字符串缓冲区的示例用法(例如从数据库读取的数据):

require "ruby-filemagic"

content = File.read("/.../sample.pdf") # just an example to get some data

fm = FileMagic.new
fm.buffer(content)    
#=> "PDF document, version 1.4"

要使 gem 工作(和编译),您需要 file 实用程序以及在系统上安装标头的 magic 库。引用自述文件:

需要文件(1)库和头文件:

Debian/Ubuntu:: +libmagic-dev+
Fedora/SuSE:: +file-devel+
Gentoo:: +sys-libs/libmagic+
OS X:: brew install libmagic

测试在 Rails 5 下运行良好。

【讨论】:

  • 嗯,当我尝试安装这个 gem 时,我仍然遇到构建错误——“检查 -lgnurx...否,*** 错误:缺少编译此模块所需的库” .我将不得不对此进行研究,然后再回来尝试您的建议。
  • 你在什么系统上尝试这个?如果卡住了,能否发布带有错误消息的完整日志?
  • 我没有按照您的建议运行“brew install libmagic”。运行确实允许安装所有内容。我无法从文档中找出一个问题——“缓冲区”是否总是以一致的方式打印出文件类型?也就是说,Excel文档总是输出“Microsoft Excel”而PDF文档总是打印出“PDF”这个词吗?
  • 好!关于您的问题,当然没有绝对的确定性,但我希望输出非常一致。 file 实用程序和相关的 magic 库已经存在很多年了,作者没有理由改变它的行为。查看 sources 库当前可识别的所有格式变体。
  • 嘿,我开始赏金这个只是因为我看不到这个 gem 打印文件类型的方式没有一致性。使用该解决方案时,我的变化太多了。
【解决方案2】:

如果你在 unix 机器上,你可以使用 file 命令:

file titi.pdf

然后您可以执行以下操作:

require 'open2'

cmd = 'file -'
Open3.popen3(cmd) do |stdin, stdout, wait_thr|
  stdin.write(content)
  stdin.close
  puts "file type is:" + stoud.read
end

【讨论】:

  • 我的生产环境是Ubuntu Linux,但我的本地环境是Mac OS X。
猜你喜欢
  • 1970-01-01
  • 2012-03-25
  • 1970-01-01
  • 2010-09-18
  • 2014-02-09
  • 2011-02-19
  • 2021-07-21
  • 2020-02-04
  • 2018-06-23
相关资源
最近更新 更多