我基本上是在图片文件的标题中阅读并进行快速比较以查看它实际上是什么类型的文件。 BMP,GIF,PNG都很简单,因为它们的标题分别包含BM,GIF和PNG以识别自己。 JPG给我带来了一些循环。
jpg的前3个字节往往是0xff \ 0xd8 \ 0xff,在我的生命中,无论我如何设置,我都无法通过简单的比较得到真正的值。
我读了前4个字节:
if data[0, 3] == "\xff\xd8\xff"
puts "This is a JPG"
end
我知道我很接近,但我无法让它发挥作用。请让我知道我在这里错过了什么。
注意:我知道有宝石为我做这个,但我不想使用宝石。就这么简单。
答案 0 :(得分:9)
这是一个字符编码问题。从JPEG中读取前4个字节将返回ASCII编码的字符串:
head = File.read("some.jpg", 4)
# => "\xFF\xD8\xFF\xE1"
head.encodig
# => #<Encoding:ASCII-8BIT>
另一方面,字符串是UTF-8编码的:
jpg_prefix = "\xff\xd8\xff"
# => "\xFF\xD8\xFF"
jpg_prefix.encoding
# => #<Encoding:UTF-8>
比较UTF-8和ASCII字符串不能按预期工作:
head[0,3] == jpg_prefix
# => false
您必须使用String#force_encoding
显式设置编码:
jpg_prefix = "\xff\xd8\xff".force_encoding(Encoding::ASCII_8BIT)
# => "\xFF\xD8\xFF"
jpg_prefix.encoding
# => #<Encoding:ASCII-8BIT>
head[0,3] == jpg_prefix
# => true
使用Integer#chr
创建的连接ASCII字符(由Mario Visic建议)也有效:
jpg_prefix = 0xff.chr + 0xd8.chr + 0xff.chr
# => "\xFF\xD8\xFF"
jpg_prefix.encoding
# => #<Encoding:ASCII-8BIT>
或者使用Array#pack
:
jpg_prefix = ["FFD8FF"].pack("H*")
# => "\xFF\xD8\xFF"
jpg_prefix.encoding
# => #<Encoding:ASCII-8BIT>
答案 1 :(得分:0)
当Data是一个字符串时,你的代码对我来说很好 - 但Data可能是一个字节值数组。
试试这个:
if data[0,3] == [0xff, 0xd8, 0xff]
作为你的条件。
答案 2 :(得分:0)
您应该能够将文件信息与字符代码进行比较,例如:
if data[0, 3] == 0xff.chr + 0xd8.chr + 0xff.chr
puts "This is a JPG"
end
如果你遇到困难,你可以随时查看fastimage gem的代码,类型检测代码在这里:https://github.com/sdsykes/fastimage/blob/master/lib/fastimage.rb#L337-L354
与其他人(@Stefan)一样,字符串在原始示例中不匹配,因为编码不同。
# Check the encodings for our strings:
"\xff\xd8\xff".encoding #=> <Encoding:UTF-8>
(0xff.chr + 0xd8.chr + 0xff.chr).encoding #=> <Encoding:ASCII-8BIT>
# Compare our two strings with different encodings:
utf8 = "\xff\xd8\xff"
ascii = 0xff.chr + 0xd8.chr + 0xff.chr
utf8 == ascii #=> false
utf8.force_encoding("ASCII-8BIT") == ascii #=> true
如果您强制编码为ASCII-8BIT
,您的原始代码实际上可以正常工作答案 3 :(得分:0)
如果可以的话,识别文件是让别人做的好事。 ruby-filemagic gem将执行此操作。
gem 'ruby-filemagic'
在使用中,它返回一个字符串:
require 'filemagic'
magic = FileMagic.new
p magic.file("/tmp/pic1.jpg")
# => "JPEG image data, JFIF standard 1.02"
返回的字符串可以与正则表达式匹配:
case magic.file(path)
when /JPEG/
# do JPEG stuff
when /GIF/
# do GIF stuff
else
# we don't recognize it
end
ruby-filemagic使用libmagic库,它识别大量文件类型。
文档有点稀疏(README甚至没有“hello world”示例),并且它在几年内没有更新,但是不要让它阻止你尝试它。这很简单,使用起来非常可靠 - 我今天使用它获得了生产代码,它仍然可以正常工作。
如果出于某种原因,您无法使用gem,但是在* nix环境中并且可以访问“file”命令,那么您可以通过炮轰“file”获得相同的功能:
p `file /tmp/pic1.jpg`
# => "/tmp/pic1.jpg: JPEG image data, JFIF standard 1.02\n
在Debian中,文件命令由包文件提供。您的操作系统可能有所不同。