使用 textscan 将 ASC 文件读入 MATLAB - 可变列长度
Read ASC file into MATLAB using textscan - variable column lengths
我正在尝试将以下数据读入 MATLAB:
'0.000000 1 18EFFA59x Rx D 8 AD 09 02 00 00 00 00 30'
'0.004245 1 14EFF01Cx Rx D 6 DB 00 FF FF 00 71'
'0.004640 1 CEF801Cx Rx D 3 3F 00 3B'
'0.005130 1 14EF131Cx Rx D 6 DB 00 FF FF 00 71'
'0.005630 1 CEF801Cx Rx D 3 3F 00 C3'
'0.010015 1 18EFFA59x Rx D 8 AD 07 01 00 00 00 00 30'
'0.014145 1 CF004F0x Rx D 8 F0 FF 7D 00 00 FF FF FF'
'0.015060 1 18EFFA59x Rx D 8 AD 07 02 00 00 00 00 30'
'0.018235 1 18EF1CF0x Rx D 8 F2 1E 05 FF FF 00 71 FF'
'0.018845 1 18EA5941x Rx D 3 09 FF 00'
我可以轻松地将每一行作为字符串读取 - 但为了使 post 处理更有效率,我想用分隔符分隔每一行 - 这是空白。换句话说,最终结果应该是一个非单例元胞数组。我似乎找不到一种非常有效的方法来做到这一点。效率很重要,因为这些文件有几百万行长,并且在 MATLAB 中使用 strings/cells 处理需要很长时间。
如有任何帮助,我们将不胜感激。谢谢
你似乎有固定宽度的字段,所以我会这样对待它,让 textscan
通过关闭定界符和空格并定义字段宽度和明确类型:
test = {...
'0.000000 1 18EFFA59x Rx D 8 AD 09 02 00 00 00 00 30'
'0.004245 1 14EFF01Cx Rx D 6 DB 00 FF FF 00 71'
'0.004640 1 CEF801Cx Rx D 3 3F 00 3B'
'0.005130 1 14EF131Cx Rx D 6 DB 00 FF FF 00 71'
'0.005630 1 CEF801Cx Rx D 3 3F 00 C3'
'0.010015 1 18EFFA59x Rx D 8 AD 07 01 00 00 00 00 30'
'0.014145 1 CF004F0x Rx D 8 F0 FF 7D 00 00 FF FF FF'
'0.015060 1 18EFFA59x Rx D 8 AD 07 02 00 00 00 00 30'
'0.018235 1 18EF1CF0x Rx D 8 F2 1E 05 FF FF 00 71 FF'
'0.018845 1 18EA5941x Rx D 3 09 FF 00'};
test = strjoin(test', '\n');
C = textscan(test, '%8.6f %2u %11s %4s %2s %2u %33s', 'delimiter', '','whitespace','');
col1 = C{1};
col2 = C{2};
col3 = strtrim(C{3});
col3 = cellfun(@(x)hex2dec(x(1:end-1)), col3); % for instance.
col4 = strtrim(C{4});
col5 = strtrim(C{5});
col6 = C{6};
col7 = strtrim(C{7});
在现实世界中,您会用文本字符串替换文件 ID。对于最后一个可变长度字段,只需读入整个内容,确保指定最大可能长度。 MATLAB 将读取一个字段,直到它到达末尾或到达换行符(事实上,我将最后一个字段的宽度增大了 1,只是为了确保)。然后将每个字段聚合到一个单元格中。我还冒昧地将第三个字段从十六进制转换为十进制,以显示您可以如何 post 进一步处理数字。
进一步说明,如果您确实有巨大的文件并且需要最大速度,您可以通过指定 %*ns
跳过字符字段上的 strtrim
步骤,其中 n 是所需的字段宽度,对于任何已知的间隙,例如第 3 列和第 4 列之间的 2 个字符的间隙。星号表示忽略该字段。然而,我发现这种处理方式更具可读性和直观性,并且在其中一个字段(例如第 4 个)偶尔有 3 个字符的条目的情况下会留下很小的误差。
我正在尝试将以下数据读入 MATLAB:
'0.000000 1 18EFFA59x Rx D 8 AD 09 02 00 00 00 00 30'
'0.004245 1 14EFF01Cx Rx D 6 DB 00 FF FF 00 71'
'0.004640 1 CEF801Cx Rx D 3 3F 00 3B'
'0.005130 1 14EF131Cx Rx D 6 DB 00 FF FF 00 71'
'0.005630 1 CEF801Cx Rx D 3 3F 00 C3'
'0.010015 1 18EFFA59x Rx D 8 AD 07 01 00 00 00 00 30'
'0.014145 1 CF004F0x Rx D 8 F0 FF 7D 00 00 FF FF FF'
'0.015060 1 18EFFA59x Rx D 8 AD 07 02 00 00 00 00 30'
'0.018235 1 18EF1CF0x Rx D 8 F2 1E 05 FF FF 00 71 FF'
'0.018845 1 18EA5941x Rx D 3 09 FF 00'
我可以轻松地将每一行作为字符串读取 - 但为了使 post 处理更有效率,我想用分隔符分隔每一行 - 这是空白。换句话说,最终结果应该是一个非单例元胞数组。我似乎找不到一种非常有效的方法来做到这一点。效率很重要,因为这些文件有几百万行长,并且在 MATLAB 中使用 strings/cells 处理需要很长时间。
如有任何帮助,我们将不胜感激。谢谢
你似乎有固定宽度的字段,所以我会这样对待它,让 textscan
通过关闭定界符和空格并定义字段宽度和明确类型:
test = {...
'0.000000 1 18EFFA59x Rx D 8 AD 09 02 00 00 00 00 30'
'0.004245 1 14EFF01Cx Rx D 6 DB 00 FF FF 00 71'
'0.004640 1 CEF801Cx Rx D 3 3F 00 3B'
'0.005130 1 14EF131Cx Rx D 6 DB 00 FF FF 00 71'
'0.005630 1 CEF801Cx Rx D 3 3F 00 C3'
'0.010015 1 18EFFA59x Rx D 8 AD 07 01 00 00 00 00 30'
'0.014145 1 CF004F0x Rx D 8 F0 FF 7D 00 00 FF FF FF'
'0.015060 1 18EFFA59x Rx D 8 AD 07 02 00 00 00 00 30'
'0.018235 1 18EF1CF0x Rx D 8 F2 1E 05 FF FF 00 71 FF'
'0.018845 1 18EA5941x Rx D 3 09 FF 00'};
test = strjoin(test', '\n');
C = textscan(test, '%8.6f %2u %11s %4s %2s %2u %33s', 'delimiter', '','whitespace','');
col1 = C{1};
col2 = C{2};
col3 = strtrim(C{3});
col3 = cellfun(@(x)hex2dec(x(1:end-1)), col3); % for instance.
col4 = strtrim(C{4});
col5 = strtrim(C{5});
col6 = C{6};
col7 = strtrim(C{7});
在现实世界中,您会用文本字符串替换文件 ID。对于最后一个可变长度字段,只需读入整个内容,确保指定最大可能长度。 MATLAB 将读取一个字段,直到它到达末尾或到达换行符(事实上,我将最后一个字段的宽度增大了 1,只是为了确保)。然后将每个字段聚合到一个单元格中。我还冒昧地将第三个字段从十六进制转换为十进制,以显示您可以如何 post 进一步处理数字。
进一步说明,如果您确实有巨大的文件并且需要最大速度,您可以通过指定 %*ns
跳过字符字段上的 strtrim
步骤,其中 n 是所需的字段宽度,对于任何已知的间隙,例如第 3 列和第 4 列之间的 2 个字符的间隙。星号表示忽略该字段。然而,我发现这种处理方式更具可读性和直观性,并且在其中一个字段(例如第 4 个)偶尔有 3 个字符的条目的情况下会留下很小的误差。