我有包含数据记录器输出的.txt文件。数据以非常特定的方式记录,每行一条消息,每条消息前面都有一条消息ID。因此,通过了解每一行的消息ID,我将知道由于消息格式将在该行上跟随什么。每条消息(不同的ID)都有不同的格式。数据的一个例子:
$GPGGA,220542.000,4745.8026,N,12211.0284,W,1,07,1.3,3.4,M,-17.2,M,,0000*67
$GPGSA,A,3,30,05,29,31,02,10,25,,,,,,2.0,1.3,1.5*3D
$GPGSV,3,1,12,29,78,315,39,05,52,080,45,30,43,288,46,25,41,196,33*72
$GPGSV,3,2,12,21,31,249,30,02,23,066,41,12,17,172,38,31,11,276,40*7F
$GPGSV,3,3,12,10,07,036,30,26,02,115,,18,01,199,,48,34,194,37*73
$GPRMC,220542.000,A,4745.8026,N,12211.0284,W,0.08,174.78,271011,,*12
$GPGGA,220543.000,4745.8025,N,12211.0284,W,1,07,1.3,3.4,M,-17.2,M,,0000*65
所有内容都以逗号分隔,但由于每一行都不同(即每条消息的格式不同),我对csv(在Matlab中)无能为力。
基本上,我想要做的是逐行搜索数据。对于每一行,我想确定消息ID,然后将该行的其余部分存储在一个数组中,因为我将知道该行的格式。最后,我将为每种消息类型提供一个数组。
我可以使用csv将所有内容放入excel中,但由于每行都不同,因此很难提取数据......我甚至不知道excel中是否可能(可能是这样)。
在Matlab中,我不能使用任何csv因为有非数值。我已经尝试直接读取文件并使用fgetl()抓取每一行,然后单步执行每一行,但必须有一种更有效的方法。我读了一些关于保存excel文件的内容,然后去matlab提取数据,但是消除那个中间步骤会很好。
关于如何解决这个问题的想法会很好。我不是在寻找任何人为我编写代码......只是为了指出我的写作方向。
哦,我认为importdata()会起作用,但我尝试了importdata('filename.txt',','),但它不会识别分隔符......?
答案 0 :(得分:1)
由于您的数据具有混合格式,因此在此过程中的某个时刻,您必须循环遍历这些行,并根据各自的格式对其进行解析。我怀疑你能够在一个简单的函数调用中解析整个事情......
这是我尝试读取文件的时候(你没有描述不同日志消息的格式,所以我必须根据显示的几行来提出我自己的文件)。
我们的想法是为每种消息类型提供日志文件中相应行的格式。我们首先从文件中读取所有行,然后从每个行中提取消息ID。接着为每个可能的消息ID,我们提取匹配的行,使用指定的格式逐个解析它们并存储提取的信息。
结果将是一个单元格数组,每个消息ID都有一个单元格。这些元素中的每一个都是独立的cellarray,以行/列的形式存储为表格。
%# line format for each type of message IDs
frmt = {
'$GPGGA', '%s %f %f %c %f %c %f %f %f %f %c %f %c %f %s' ;
'$GPGSA', '%s %c %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %s' ;
'$GPGSV', '%s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %s' ;
'$GPRMC', '%s %f %c %f %c %f %c %f %f %f %f %s' ;
};
%# read log file as lines
fid = fopen('log.txt','rt');
C = textscan(fid, '%s', Inf, 'Delimiter','\n'); C = C{1};
fclose(fid);
%# get message ID of each line
msgId = strtok(C,',');
%# for each possible message ID
arr = cell(size(frmt,1),1);
for m=1:size(frmt,1)
%# get lines matching this ID
lines = C( ismember(msgId,frmt{m,1}) );
%# parse lines using specified format
arr{m} = cell(numel(lines), sum(frmt{m,2}=='%'));
for i=1:numel(lines)
arr{m}(i,:) = textscan(lines{i}, frmt{m,2}, 'Delimiter',',');
end
%# flatten nested cells containing strings
idx = cellfun(@iscell, arr{m}(1,:));
arr{m}(:,idx) = cellfun(@(x)x, arr{m}(:,idx));
end
$GPGGA,220542.000,4745.8026,N,12211.0284,W,1,07,1.3,3.4,M,-17.2,M,,0000*67
$GPGSA,A,3,30,05,29,31,02,10,25,,,,,,2.0,1.3,1.5*3D
$GPGSV,3,1,12,29,78,315,39,05,52,080,45,30,43,288,46,25,41,196,33*72
$GPGSV,3,2,12,21,31,249,30,02,23,066,41,12,17,172,38,31,11,276,40*7F
$GPGSV,3,3,12,10,07,036,30,26,02,115,,18,01,199,,48,34,194,37*73
$GPRMC,220542.000,A,4745.8026,N,12211.0284,W,0.08,174.78,271011,,*12
$GPGGA,220543.000,4745.8025,N,12211.0284,W,1,07,1.3,3.4,M,-17.2,M,,0000*65
上述文件的结果:
>> arr
arr =
{2x15 cell}
{1x18 cell}
{3x20 cell}
{1x12 cell}
例如,匹配messageID = $GPGGA
的行是:
>> arr{ ismember(frmt(:,1),'$GPGGA') } %# arr{1}
ans =
'$GPGGA' [220542] [4745.8] 'N' [12211] 'W' [1] [7] [1.3] [3.4] 'M' [-17.2] 'M' [NaN] '0000*67'
'$GPGGA' [220543] [4745.8] 'N' [12211] 'W' [1] [7] [1.3] [3.4] 'M' [-17.2] 'M' [NaN] '0000*65'