BinData - 在Ruby中解析二進制數據

參考:https://github.com/dmendel/bindata/wiki

BinData提供了一種聲明性方式來讀取和寫入結構化二進制數據。

這意味著程序員指定二進制數據的格式为肮,BinData設計出如何以這種格式讀寫數據往踢。 這是一個更容易(和更可讀)的替代ruby的#pack和#unpack方法突勇。

導航

安裝
您可以通過rubygems安裝BinData幔摸。
gem install bindata
或者簽出代碼:
git clone https://github.com/dmendel/bindata.git

概述
BinData聲明很容易閱讀。 這里有一個例子骚秦。
class MyFancyFormat < BinData::Record
stringz :comment
uint8 :len
array :data, :type => :int32be, :initial_length => :len
end
這種花哨的格式描述以下數據集合:

:comment:一個零終止的字符串

:len:無符號8位整數

:data:無符號32位高端整數序列她倘。 整數的數量由以下值表示:len
BinData聲明與英語描述緊密匹配。 將上述聲明與等效的#unpack代碼進行比較作箍,以讀取這樣的數據記錄硬梁。
def read_fancy_format(io)
comment, len, rest = io.read.unpack("ZCa")
data = rest.unpack("N#{len}")
{:comment => comment, :len => len, :data => *data}
end

BinData聲明清楚地顯示了記錄的結構。 #unpack代碼使此結構不透明胞得。

BinData的一般用法是將數據的結構化集合聲明為用戶定義的記錄荧止。 該記錄可以被實例化,讀取阶剑,寫入和操縱跃巡,而用戶不必關心基本的二進制數據表示。

記錄
BinData記錄聲明的一般格式是包含一個或多個字段的類牧愁。
class MyName < BinData::Record
type field_name, :param1 => "foo", :param2 => bar, ...
...
end
type :是提供的類型的名稱(例如uint32be素邪,string,array)或用戶定義的類型猪半。 對于用戶定義的類型兔朦,類名稱從CamelCase轉換為lowercased underscore_style
field_name:是您可以訪問該字段的名稱。 使用符號作為名稱磨确。 如果省略名稱烘绽,則此特定字段為匿名。 匿名字段仍在讀取和寫入俐填,但不會出現在#snapshot中。
每個字段可以具有用于如何處理數據的可選參數翔忽。 參數作為帶有符號的哈希鍵傳遞英融。 參數被設計為懶惰評估,可能多次歇式。 這意味著任何參數值都不能有副作用驶悟。

以下是參數的合法值的一些示例。

:param => 5
:param => lambda {foo + 2}
:param =>:bar
最簡單的情況是值為字面值材失,例如5痕鳍。

如果值不是文字,它應該是一個lambda龙巨。 將在父級的上下文中評估lambda笼呆。 在這種情況下,父項是MyName的實例旨别。

如果值是一個符號诗赌,它將作為包含符號值的lambda的語法糖。 例如:param =>:bar等效于:param => lambda {bar}
指定默認字節(jié)序
數字類型的字節(jié)順序必須明確定義秸弛,以便生成的代碼獨立于架構铭若。 但是洪碳,為每個數字字段顯式指定endian可能導致難以閱讀的膨脹聲明。
class A < BinData::Record
int16be :a
int32be :b
int16le :c # <-- Note little endian!
int32be :d
float_be :e
array :f, :type => :uint32be
end
endian關鍵字可用于設置默認字節(jié)序叼屠。 這使得聲明更容易閱讀瞳腌。 不使用默認邊框的任何數字字段可以顯式覆蓋它。
class A < BinData::Record
endian :big

int16 :a
int32 :b
int16le :c # <-- Note how this little endian now stands out
int32 :d
float :e
array :f, :type => :uint32
end
通過上述示例可以看出清晰度的增加镜雨。 endian關鍵字將級聯到嵌套類型嫂侍,如上例中的數組所示。
基本類型
Endian with custom types
endian關鍵字也可以用于標識具有字節(jié)順序的自定義類型冷离。 為此吵冒,自定義類型的類名必須以Le結尾,對于小尾數西剥,Be為大尾痹栖。
class CoordLe < BinData::Record
endian :little
int16 :x
int16 :y
end

class CoordBe < BinData::Record
endian :big
int16 :x
int16 :y
end

class Rectangle < BinData::Record
endian :little
coord :upper_left # <-- Here CoordLe is automatically
coord :lower_right # <-- assumed
end
聲明兩個:big和:little endian自定義類型

復合類型
常見操作
高級主題
高級I / O
常問問題
如何使用字符串編碼與BinData?
備擇方案
這一部分純屬歷史瞭空。 BinData的所有替代方法不再被積極維護揪阿。

BinData有幾種替代方法。下面是BinData和其替代品之間的比較咆畏。

簡短的形式是南捂,BinData是大多數情況下的最佳選擇。它是所有替代品中最全面的旧找。它也可以說是最可讀和最簡單的方法來解析和寫入二進制數據溺健。

BitStruct

BitStruct是所有替代品中最完整的。它是聲明性的钮蛛,并支持大多數與BinData相同的原始類型鞭缭。它的特殊功能是報告生成的自我記錄功能。 BitStruct的設計選擇是偏好速度超過靈活性魏颓。

BitStruct的主要限制是它不支持可變長度字段和依賴字段岭辣。這使得它很難處理任何非平凡的文件格式。

如果速度很重要甸饱,你只處理簡單的二進制數據類型沦童,那么BitStruct可能是一個不錯的選擇。對于非平凡數據類型叹话,BinData是更好的選擇偷遗。

二進制稀疏

BinaryParse是一個聲明式樣的打包器/解包器。它提供了與Ruby的#pack相同的原語渣刷,增加了日期和時間鹦肿。像BitStruct,它不提供依賴或可變長度字段辅柴。

BinStruct

BinStruct是解包二進制數據的命令式方法箩溃。它提供了一些聲明性語法糖瞭吃。它支持最常見的基本類型,以及任意長度的位域涣旨。

它的主要焦點是作為一個二進制模糊器歪架,而不是一個通用的解碼/編碼庫。

可包裝

Packable使它更好地使用Ruby的#pack和#unpack方法霹陡。而不是必須記住和蚪,例如“n”是打包16位大端整數的代碼,可壓縮提供了許多方便的快捷方式烹棉。在“n”的情況下攒霹,可以使用{:bytes => 2,:endian =>:big}浆洗。

使用Packable提高了#pack和#unpack方法的可讀性催束,但顯式調用#pack和#unpack并不像聲明方法那樣可讀。

Bitpack

Bitpack提供從八位字節(jié)流中提取任意位長的大端整數的方法伏社。

提取代碼是用C編寫的抠刺,所以如果速度很重要,位操作是所有你需要的功能摘昌,那么這可能是一個替代方法速妖。這一節(jié)純粹是歷史的。 BinData的所有替代方法不再被積極維護聪黎。

BinData有幾種替代方法罕容。下面是BinData和其替代品之間的比較。

簡短的形式是BinData是大多數情況下的最佳選擇稿饰。它是所有替代品中最全面的杀赢。它也可以說是最可讀和最簡單的方法來解析和寫入二進制數據。

BitStruct

BitStruct是所有替代品中最完整的湘纵。它是聲明性的,并支持大多數與BinData相同的原始類型滤淳。它的特殊功能是報告生成的自我記錄功能梧喷。 BitStruct的設計選擇是偏好速度超過靈活性。

BitStruct的主要限制是它不支持可變長度字段和依賴字段脖咐。這使得它很難處理任何非平凡的文件格式铺敌。

如果速度很重要,你只處理簡單的二進制數據類型屁擅,那么BitStruct可能是一個不錯的選擇偿凭。對于非平凡數據類型,BinData是更好的選擇派歌。

二進制稀疏

BinaryParse是一個聲明式樣的打包器/解包器弯囊。它提供了與Ruby的#pack相同的原語痰哨,增加了日期和時間。像BitStruct匾嘱,它不提供依賴或可變長度字段斤斧。

BinStruct

BinStruct是解包二進制數據的命令式方法。它提供了一些聲明性語法糖霎烙。它支持最常見的基本類型撬讽,以及任意長度的位域。

它的主要焦點是作為一個二進制模糊器悬垃,而不是一個通用的解碼/編碼庫游昼。

可包裝

Packable使它更好地使用Ruby的#pack和#unpack方法。而不是必須記住尝蠕,例如“n”是打包16位大端整數的代碼烘豌,可壓縮提供了許多方便的快捷方式。在“n”的情況下趟佃,可以使用{:bytes => 2扇谣,:endian =>:big}。

使用Packable提高了#pack和#unpack方法的可讀性闲昭,但顯式調用#pack和#unpack并不像聲明方法那樣可讀罐寨。

Bitpack

Bitpack提供從八位字節(jié)流中提取任意位長的大端整數的方法。

提取代碼用C編寫序矩,因此如果速度很重要鸯绿,位操作是所有你需要的功能,那么這可能是一個替代簸淀。
它是什么瓶蝴?
你有沒有發(fā)現自己寫這樣的代碼?
io = File.open(...)
len = io.read(2).unpack("v")[0]
name = io.read(len)
width, height = io.read(8).unpack("VV")
puts "Rectangle #{name} is #{width} x #{height}"

這是丑陋租幕,違反DRY舷手,感覺像你在寫Perl,而不是Ruby劲绪。
有一個更好的方法男窟。
class Rectangle < BinData::Record
endian :little
uint16 :len
string :name, :read_length => :len
uint32 :width
uint32 :height
end

io = File.open(...)
r = Rectangle.read(io)
puts "Rectangle #{r.name} is #{r.width} x #{r.height}"

BinData使您可以輕松地指定要操作的數據的結構。

它支持在結構化二進制數據中找到的所有常見數據類型贾富。 支持依賴和可變長度字段歉眷。BinData使您可以輕松地指定要操作的數據的結構。

它支持在結構化二進制數據中找到的所有常見數據類型颤枪。 支持依賴和可變長度字段汗捡。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市畏纲,隨后出現的幾起案子扇住,更是在濱河造成了極大的恐慌春缕,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件台囱,死亡現場離奇詭異淡溯,居然都是意外死亡,警方通過查閱死者的電腦和手機簿训,發(fā)現死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門咱娶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人强品,你說我怎么就攤上這事膘侮。” “怎么了的榛?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵琼了,是天一觀的道長。 經常有香客問我夫晌,道長雕薪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任晓淀,我火速辦了婚禮所袁,結果婚禮上,老公的妹妹穿的比我還像新娘凶掰。我一直安慰自己燥爷,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布懦窘。 她就那樣靜靜地躺著前翎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪畅涂。 梳的紋絲不亂的頭發(fā)上港华,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機與錄音午衰,去河邊找鬼苹丸。 笑死,一個胖子當著我的面吹牛苇经,可吹牛的內容都是我干的。 我是一名探鬼主播宦言,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼扇单,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奠旺?” 一聲冷哼從身側響起蜘澜,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤施流,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鄙信,有當地人在樹林里發(fā)現了一具尸體瞪醋,經...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年装诡,在試婚紗的時候發(fā)現自己被綠了银受。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸦采,死狀恐怖宾巍,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情渔伯,我是刑警寧澤顶霞,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站锣吼,受9級特大地震影響选浑,放射性物質發(fā)生泄漏。R本人自食惡果不足惜玄叠,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一古徒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诸典,春花似錦描函、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肌蜻,卻和暖如春互墓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒋搜。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工篡撵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豆挽。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓育谬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親帮哈。 傳聞我的和親對象是個殘疾皇子膛檀,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理揽趾,服務發(fā)現贬养,斷路器,智...
    卡卡羅2017閱讀 134,638評論 18 139
  • about 這篇文章是Python2 的官方文檔 7.3. struct — Interpret strings ...
    龐貝船長閱讀 6,248評論 1 3
  • 由于工程項目中擬采用一種簡便高效的數據交換格式,百度了一下發(fā)現除了采用 xml笆呆、JSON 還有 ProtoBuf(...
    黃海佳閱讀 48,594評論 1 23
  • 1. 和朋友一起吃飯枫浙,餐廳很漂亮刨肃。心情很好,聊正事自脯,也開玩笑之景。 不和諧的聲音是這時候傳過來的「喑保“不是說讓你們別點飲...
    言君閱讀 644評論 0 51
  • 討論的目標是為了讓自己更明白 爭論的目標是為了徹底說服對方 爭論的沖動常常來自于自己的弱小锻狗,不是人微言輕,而是人微易怒
    格魯特的日記閱讀 1,785評論 0 0