fromfile
和tofile
既可以读写二进制文件,也可以读写文本文件,是非常灵活的文件读取函数。
考虑到大家手头没有合适的文件以供读写,所以先讲解tofile
,其定义为
ndarray.tofile(fid, sep='', format='%s')
其中sep
表示分隔符,当sep
为空(''
)时,将存储为二进制文件,否则存储为文本。当存储为文本时,可通过format
来设置文本的存储格式。
import numpy as np
x = np.random.randint(10, size=[5,10])
print(x)
'''
[[8 5 5 4 1 5 9 0 8 8]
[1 4 9 2 2 8 6 3 0 8]
[0 6 7 8 9 0 6 6 2 1]
[2 8 6 0 5 0 4 8 6 8]
[3 0 1 3 5 9 7 1 6 5]]
'''
x.tofile("test.bin")
由于sep
默认为''
,所以test.bin
是二进制文件,为了确认这一点,可以打开看一下
>>> x.tofile("test.bin")
>>> with open('test.bin', 'rb') as f:
... f.read()
...
b'\x08\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\x00\x06\x00\x00\x00\x08\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\t\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00\x00'
可以看出其存储的内容以4个字节为一组,并且高位高地址,0x08 0x00 0x00 0x00
正是8,0x05 0x00 0x00 0x00
正是5,依次类推。
如果对sep
赋了值,那么存储内容也会相应地发生变化
x.tofile('test.txt', sep='|')
这个test.txt
可以直接打开,内容是
8|5|5|4|1|5|9|0|8|8|1|4|9|2|2|8|6|3|0|8|0|6|7|8|9|0|6|6|2|1|2|8|6|0|5|0|4|8|6|8|3|0|1|3|5|9|7|1|6|5
format
可以指明输出文档的数字格式,例如
x.tofile('test.txt', sep=',', format="%f")
所得到的test.txt
中,数字就会有小数点。
fromfile
相当于是tofile
的对偶函数,其定义为
fromfile(file, dtype=float, count=-1, sep='', offset=0, *, like=None)
其中file, sep
自不必说,dtype
表示读取之后赋予的数据类型,count
表示读取的项目;offset
表示偏移量;like
为一个数组,这个数组决定读取数据之后输出数组的形状。
如果不声明dtype
,则会默认为是float
类型,从而导致灾难性后果
>>> y = np.fromfile('test.bin')
>>> y
array([1.06099790e-313, 8.48798317e-314, 1.06099790e-313, 4.44659081e-323,
1.69759663e-313, 8.48798316e-314, 4.24399159e-314, 1.69759663e-313,
6.36598738e-314, 1.69759663e-313, 1.27319747e-313, 1.69759663e-313,
4.44659081e-323, 1.27319747e-313, 2.12199579e-314, 1.69759663e-313,
2.96439388e-323, 2.47032823e-323, 1.69759663e-313, 1.69759663e-313,
1.48219694e-323, 6.36598737e-314, 1.90979621e-313, 2.12199579e-314,
1.06099790e-313])
由于此前用tofile
保存的是整型,所以读取的时候也得是整型
>>> y = np.fromfile('test.bin', dtype=int)
>>> print(y)
[8 5 5 4 1 5 9 0 8 8 1 4 9 2 2 8 6 3 0 8 0 6 7 8 9 0 6 6 2 1 2 8 6 0 5 0 4
8 6 8 3 0 1 3 5 9 7 1 6 5]
这回味儿就对了。
而且二进制和文本一定要注意区分,即sep
不能弄错,否则也会无法读取到想要的数据
>>> y = np.fromfile('test.bin', dtype=int, sep=',')
<stdin>:1: DeprecationWarning: string or file could not be read to its end due to unmatched data; this will raise a ValueError in the future.
>>> y
array([], dtype=int32)
>>> y = np.fromfile('test.txt', sep=',')
>>> y
array([8., 5., 5., 4., 1., 5., 9., 0., 8., 8., 1., 4., 9., 2., 2., 8., 6.,
3., 0., 8., 0., 6., 7., 8., 9., 0., 6., 6., 2., 1., 2., 8., 6., 0.,
5., 0., 4., 8., 6., 8., 3., 0., 1., 3., 5., 9., 7., 1., 6., 5.])