【问题标题】:Reading file starting at end in MATLAB在 MATLAB 中从末尾开始读取文件
【发布时间】:2011-06-30 23:51:03
【问题描述】:
我想知道是否有人知道如何在 MATLAB 中打开和读取文件,您从文件末尾开始读取。该文件不断更新(在读取之间以一些不恒定的速率),我想每次都读取文件的最后六行。
我还想包含一个测试来验证我不会重复阅读相同的行两次。每一行的格式如下(每个变量都是一个浮点数):
timestamp accx accy accz gyrox gyroy gyroz magx magy magz
我尝试使用 fseek 将位置更改为文件的最后一行,但这仅允许我读取我认为的文件的最后一行,而不是向后读取文件,除非我指定一定数量的字节,我不知道确切的字节数。
【问题讨论】:
标签:
matlab
file-io
eof
tail
fseek
【解决方案1】:
如果您使用的是基于 unix 的系统 (Linux/Mac),您可以直接使用系统命令来做您想做的事。这是一个示例测试文件:
12345 accx accy accz gyrox gyroy gyroz magx magy magz
23456 accx accy accz gyrox gyroy gyroz magx magy magz
34567 accx accy accz gyrox gyroy gyroz magx magy magz
45678 accx accy accz gyrox gyroy gyroz magx magy magz
56789 accx accy accz gyrox gyroy gyroz magx magy magz
67890 accx accy accz gyrox gyroy gyroz magx magy magz
您可以在 unix 上使用 tail 读取它,并使用 system 命令直接进入 MATLAB。
[~, str]=system('tail -n 2 filename')
str =
56789 accx accy accz gyrox gyroy gyroz magx magy magz
67890 accx accy accz gyrox gyroy gyroz magx magy magz
将-n 2 中的2 替换为您想阅读的行数。
接下来,为确保您阅读的是同一行,您可能需要存储时间戳(第一列)。最简单的方法是再次让 unix 为你做这件事
[~, timestamp]=system('tail -n 2 filename | awk ''{print $1}''')
timestamp =
56789
67890
使用str2num 将其转换为数字,并在您每次读取时存储这些数据,然后使用函数ismember 检查新时间戳是否已经是您之前读取的时间戳的一部分。
【解决方案2】:
知道你正在从文件中读取哪一行的唯一方法是从头开始计算换行符。没有办法从文件末尾开始,直接向后查找一定行数。
您可以编写一个函数,从文件末尾向后读取,直到它看到 N 个换行符,然后输出这个块。这正是tail 的工作原理。这是来自 GNU tail.c 的评论:
/* Print the last N_LINES lines from the end of file FD.
Go backward through the file, reading `BUFSIZ' bytes at a time (except
probably the first), until we hit the start of the file or have
read NUMBER newlines.
START_POS is the starting position of the read pointer for the file
associated with FD (may be nonzero).
END_POS is the file offset of EOF (one larger than offset of last byte).
Return true if successful. */
如果文件不是太大,最简单的做法是编写一个函数,一次读取一行,只保留最后 N 行。
【解决方案3】:
您可以搜索文件的结尾块(使用 fseek() 在 6 行之前设置 EOF 的位置,然后搜索最后 6 或 7 个换行符并使用 find()。然后你可以提取您的数据,因为您知道最后 6 行在您读取的原始块中的位置。
fid=fopen(filename,'r');
fseek(fid,500,'eof');
dat=fread(fid,Inf,'*char');
linestart=find(dat=="\n",7,'last'); % choose 7 newlines because there will be one at the end?