【问题标题】:Extracting data from .txt in Matlab - Tried importdata()在 Matlab 中从 .txt 中提取数据 - 尝试过 importdata()
【发布时间】:2011-10-28 21:56:40
【问题描述】:

我有 .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',','),但它无法识别分隔符...?

【问题讨论】:

    标签: matlab file-io


    【解决方案1】:

    由于您的数据具有混合格式,因此在此过程中的某个时间点,您必须遍历这些行并根据各自的格式对其进行解析。我怀疑你是否能够在一个简单的函数调用中解析整个事情......

    这是我尝试读取您提供的文件(您没有描述不同日志消息的格式,所以我不得不根据显示的几行提出自己的)。

    我们的想法是为每种消息类型提供日志文件中相应行的格式。我们首先从文件中读取所有行,并从中提取消息 ID。接下来,对于每个可能的消息 ID,我们提取匹配的行,使用指定的格式逐一解析它们并存储提取的信息。

    结果将是一个元胞数组,每个消息 ID 对应一个元胞。这些元素中的每一个都将是一个单独的单元阵列,将读取的行/列存储为表格。

    %# 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'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多