Matlab⽤fread、fwrite实现⼤⽂件读写
最近在分析⼀个35G的⼤数据⽂件,猛⼀看,是不是很吓⼈啊,不过还好,师兄写⽂件的格式⾮常规范,读取数据来也就很⽅便了,主要是使⽤了读写⽂件的两个函数fread和fwrite,下⾯⽤matlab简单尝试⼀下,对于这种⽂件读取的低级函数,c和matlab功能都是差不多的。
先来看fwrite,最简单的⽤法如下
%%
x = 1:15;
dataw = reshape(x, 5, 3);
disp(dataw)
%%
filename = 'test.bin';
hfile = fopen(filename, 'w');
fwrite(hfile, dataw, 'double');
fclose(hfile);
fwrite写矩阵,是按列来写的,即先写第⼀列,再第⼆列,以此类推。如上⾯的代码,x为
1    6    11
2    7    12
3    8    13
4    9    14
5    10    15
如果把数据全部读出来,就是
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
稍复杂的写法是,可以跳着写,就是每个数据先跳⼏个位置,然后再写数据,如上⾯的5X3矩阵,如果想按⾏来写,当然最简单的⽅式是先转置⼀下再写,但如果数据量⾮常⼤,⽽且还在另⼀个⽂件⾥,总不能先都读取进来,再转置、写,当然这只是⼀种特殊情况,但跳着写在某些时候确实是好的解决⽅法,如下实现按⾏写
fread和fwrite的区别
%%
x = 1:15;
dataw = reshape(x, 5, 3);
disp(dataw)
len = 5;
count = 3;
%%
filename = 'test.bin';
hfile = fopen(filename, 'w');
fwrite(hfile, zeros(count, 1), 'double'); % 先写⼀⾏0,因为fwrite总是先跳再写,对于第⼀⾏也要先跳,那就先在第⼀⾏补个零吧
for i = 1:count
fseek(hfile, 8*i, 'bof'); % 常常要配合fseek使⽤ fseek(fid,offset,origin);
% double 在matlab 中是 'real*8' 表⽰64位共8字节的浮点数
%所以上⾯的fwrite(hifle,zeros(count,….) 写⼊了24个字节的数据
%因为fwrite写⼊数据后会把当前指针hfile移动到最后⼀个字节位置,所以此时ftell(hfile)就为24了
fwrite(hfile, dataw(1:end, i), 'double', 8*(count-1)); % fwrite(fid,A,precision,skip)
%fwrite(hfile,dataw(1:end,1),…)这⼀⾏表⽰将dataw矩阵中的第⼀列数据1 2 3 4 5 每隔16个字节(因为这⾥⽤的double型,每个数据位占⽤了8字节)写⼊⼀个数据
%因为fwrite()是先跳后写⼊,即在写⼊dataw中第⼀列的第⼀个数据值1之前hfile在当前指针所指字节数的位置向前跳8*(count-1)个字节,然后写⼊这个数
值1(这个1占⽤了8个字节,共64位),然后再跳8*(count-1)个字节,接着写⼊数值2(dataw的第⼀列第⼆个值),直到把这列数据写完!然后继续循环
%dataw(1:end,i)表⽰取矩阵的第i列,可写为dataw(:,i)
fclose(hfile);
hfile = fopen(filename, 'r');
datar = fread(hfile, 100, 'double')
fclose(hfile);
结果如下
1    6    11
2    7    12
3    8    13
4    9    14
5    10    15
datar =
1
6
11
2
7
12
3
8
13
4
9
14
5
10
15
fwrite写的⽂件再配合上fread读,那真是天作之合了,35G的数据也是浮云啊!最简单的读取⽅式就是上⾯的
datar = fread(hfile, 100, 'double')
直接读取100个数据。当然更灵活的是跳着读,如下⾯的程序
%%
x = 1:15;
dataw = reshape(x, 5, 3);
disp(dataw)
%%
filename = 'test.bin';
hfile = fopen(filename, 'w');
fwrite(hfile, dataw, 'double');
fclose(hfile);
%% 跳着读
ind = 2; % 读第⼏时刻的数据
len = 5; % ⼀次数据的长度
hfile = fopen(filename, 'r');
fseek(hfile, 8*(ind - 1), 'bof');
datar = fread(hfile, 3, 'double', 8*(len - 1)); % double为8个字节
fclose(hfile);
disp(datar)
结果如下
1    6    11
2    7    12
3    8    13
4    9    14
5    10    15
2
12
这意思就是,⽂件中存储的数据为1到15,但如果我想读取上⾯矩阵中的第⼀⾏,即1,6,11,那就可以跳着读,但注意跳着读时,第⼀个数据是不跳直接读的,帮助⾥的说明是skips skip bytes after reading each value,这是和fwrite不同的地⽅,skips skip bytes before writing each value,所以上⾯fwrite跳着写的时候要先补⼀下0,再跳着写,⽅便⼀些。
源⽂档 <>