当你准确知道要移动光标的位置(或多少字节)时, fseek文件中的指针才有用。 当您只想跳过一些已知长度的记录时,它对二进制文件非常有用。 但是在文本文件中它比任何东西都更危险和混乱( 除非你绝对确定每一行的大小相同,并且该行上的每个元素都在同一个确切的位置/列,但这不会经常发生 )。
有几种方法可以逐块读取文本文件:
1)使用HeaderLines选项
为了简单地跳过行的块上的文本文件,你可以使用HeaderLines的参数textscan ,因此,例如:
readFormat = '%f %f %f %f %f %f %f' ; %// read format specifier
nLines = 10000 ; %// number of line to read per block
fileInfo = dir(fileName);
%// read FIRST block
fid = fileopen(fileName);
M = textscan(fid, readFormat, nLines,'Delimiter',' '); %// read the first 10000 lines
fclose(fid)
%// Now do something with your "M" data
然后当你想要读取第二个块时:
%// later read the SECOND block:
fid = fileopen(fileName);
M = textscan(fid, readFormat, nLines,'Delimiter',' ','HeaderLines', nLines); %// read lines 10001 to 20000
fclose(fid)
如果你有很多块,对于第Nth块,只需适应:
%// and then for the Nth BLOCK block:
fid = fileopen(fileName);
M = textscan(fid, readFormat, nLines,'Delimiter',' ','HeaderLines', (N-1)*nLines);
fclose(fid)
如果需要(如果你有很多块),只需在循环中编写最后一个版本。
请注意,如果在每个块读取后关闭文件,这是很好的(因此当您再次打开文件时,文件指针将从文件的开头开始)。 如果您的处理可能需要很长时间或者可能出错,那么在读取数据块后关闭文件会更安全(如果崩溃,您不希望文件保持打开太长或松散fid )。
2)逐块读取(不关闭文件)
如果块的处理足够快速和安全,所以你确定它不会爆炸,你可以负担得起不关闭文件。 在这种情况下, textscan文件指针将停留在您停止的位置,因此您还可以:
读取一个块(不要关闭文件): M = textscan(fid, readFormat, nLines)
处理它然后保存你的结果(和释放内存)
使用相同的调用读取下一个块: M = textscan(fid, readFormat, nLines)
在这种情况下,您不需要headerlines参数,因为textscan将继续读取它停止的确切位置。
3)使用ftell和fseek
最后,你可以使用fseek开始在你想要的精确位置读取文件,但在这种情况下,我建议将它与ftell结合使用。
ftell将在打开的文件中返回当前位置,因此使用它来知道您最后停止读取的位置,然后在下一次使用fseek直接在此位置。 就像是:
%// read FIRST block
fid = fileopen(fileName);
M = textscan(fid, readFormat, nLines,'Delimiter',' ');
lastPosition = ftell(fid) ;
fclose(fid)
%// do some stuff
%// then read another block:
fid = fileopen(fileName);
fseek( fid , 'bof' , lastPosition ) ;
M = textscan(fid, readFormat, nLines,'Delimiter',' ');
lastPosition = ftell(fid) ;
fclose(fid)
%// and so on ...