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*')
end
File.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=2
LONGLONG_size=8
File.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 struct
arr=array(range(5))
with open("a.bin","wb") as f:
f.write(struct.pack('5i',*arr))
读二进制文件,注意和上面保存的文件没有关系,这个稍微复杂些
大致是先读出矩阵的高,宽,然后读出这个矩阵
INTSIZE=4
FLOATSIZE=4
img_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)
针对python读写二进制参考的网址
1. struct pack 与C对应的参考
2. 如何能够保存numpy的数组
X = numpy.array([[1,2,3],[4,5,6]])
b = struct.pack('=%sf' % X.size, *X.flatten('F'))
能想到的作用
比如机器学习中如果自己写一些训练的模型,可以先用ruby实现,训练后,保存为二进制文件然后由c/c++读取并应用。