ruby/python利用pack unpack读取二进制文件

来源:互联网 发布:心神战斗机 知乎 编辑:程序博客网 时间:2024/04/29 04:46

ruby的pack和unpack方法其实和python里面的struct的pack和unpack的方法是一样的(具体使用起来有区别),能够和c语言类型(确切是系统类型)进行交互。
比如说c语言的整型是4个字节,而ruby的int其实是个类根本无法统一,这样读写二进制文件肯定不对,于是可以用Array#pack String#unpack来解决

参考资料

Ruby string pack unpack 详细用法 貌似是老版本的所以其例子是有问题的,自己就被这个文章把思路搞混了。【自己实践一下就知道了】
ruby Array#pack String#unpack 实例 这个有些基础还行

读写二进制文件的例子

这里就抛砖引玉,写个最简单的例子。

a = [0,1,2,3,4,5,6,7,8,9,10]File.open("a.bin","wb") do|fp|    fp.write a.pack('i*')endFile.open("a.bin","rb") do|fp|    int=fp.sysread(12) # 4*3 也就是读取3个    p int  # 可以用16进制打开a.bin文件与这个比对就知道了    p int.unpack('i*') end

结果如下
=> "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00"
=> [0, 1, 2]

在二进制文件中随意定位读取

下面的例子是,打开二进制文件,然后定位到文件结束前的8个字节处,读取一个c语言中的size_t(无符号 longl ong),然后返回开头读取一个无符号short型

SHORT_int_size=2LONGLONG_size=8File.open(f_split,"rb") do |fp|    p fp.seek(-LONGLONG_size, IO::SEEK_END)    line_num=fp.sysread(LONGLONG_size)    line_num,=line_num.unpack('Q')    p line_num    p fp.seek(0, IO::SEEK_SET) # 又定位到行首    feat_dim=fp.sysread(SHORT_int_size)    #S表示无符号  然后逗号后不写表示只取数组中的第一个元素    feat_dim,=feat_dim.unpack('S') end

python的例子
写二进制文件

import structarr=array(range(5))  with open("a.bin","wb") as f:    f.write(struct.pack('5i',*arr))

读二进制文件,注意和上面保存的文件没有关系,这个稍微复杂些
大致是先读出矩阵的高,宽,然后读出这个矩阵

INTSIZE=4FLOATSIZE=4img_pixel_poss=[]with open(featfile,"rb") as f:    # (feat_dim,)=struct.unpack('I',f.read(INTSIZE))    for id in range(test_num):        (h,w)=struct.unpack("2I",f.read(INTSIZE*2))        arr=struct.unpack(str(h*w)+"f",f.read(h*w*FLOATSIZE))        arr=np.array(arr).reshape(h,w)        img_pixel_poss.append(arr)

能想到的作用

比如机器学习中如果自己写一些训练的模型,可以先用ruby实现,训练后,保存为二进制文件然后由c/c++读取并应用。

0 0
原创粉丝点击