在Matlab中从.txt中提取数据 - 尝试importdata()

时间:2011-10-28 21:56:40

标签: matlab file-io

我有包含数据记录器输出的.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',','),但它不会识别分隔符......?

1 个答案:

答案 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

log.txt的

$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'