在Matlab中读取具有不同行开头数据的文本文件

时间:2018-02-12 19:44:28

标签: matlab

#- created from binary Format 
#0-Mon, 08 Jan 2018 22:43:37 GMT  
#1-Mon, 08 Jan 2018 22:49:21 GMT  

[data1:100]
0.05488 20.096462
0.10464 20.096462
0.15456 20.032051
0.20432 20.096462
0.25408 20.096462
#--finish--

[adudatal]
0.00686656
0.0121767
0.016571298
0.016388189
0.0039368276
-0.0057679103
#--finish--

数据不会始终在标题文本后的同一行开始,因此以下代码不起作用:

fid = fopen('data.txt','rt');
A = textscan(fid, '%f', 'HeaderLines',3);
A = A{1};
fclose(fid);

M = dlmread(filename,delimiter,[R1 C1 R2 C2])

如何只阅读数据?

2 个答案:

答案 0 :(得分:1)

实际上,使用传统的IO功能很难解析文件结构。由于它们无法满足您的目的,因此可能需要手动方法,包括逐行读取文件并在达到适当的偏移量后对其进行解析:

adudatal = [];
reading = false;

fid = fopen('data.txt','r');

while (~feof(fid))
    line = fgets(fid);

    if (strcmp(strtrim(line),'[adudatal]'))
        reading = true;
        continue;
    end

    if (~reading)
        continue;
    end

    if (strcmp(strtrim(line),'#--finish--'))
        break;
    end

    adudatal(end+1) = sscanf(line,'%f');
end

fclose(fid);

输出:

adudatal = 
    [0.006866560000000 0.012176700000000 0.016571298000000 0.016388189000000 0.003936827600000 -0.005767910300000]

答案 1 :(得分:0)

更快的方法是将整个文件加载到字符串中,然后使用正则表达式在解析之前提取所需的内容。

我不清楚您要提取哪些数据。假设你想从上面的例子中提取两组数据,其中每个数据集在[???]和# - finish -

之间。
Text = fileread('data.txt')
data1 = str2num(regexp(Text, '(?<=\[data1:100\]).*?(?=#--finish--)', 'match', 'once');
adudatal = str2num(regexp(Text, '(?<=\[adudatal\]).*?(?=#--finish--)', 'match', 'once');

正则表达式似乎令人生畏,并且有很多方法可以获得相同的结果,但它们非常强大。我将完成上述操作。第一行只是将文件读入字符串。第二个将数字提取为字符串,然后将其转换为数字数组。

(?&lt; = [some text])找到前面带有 [some text] 的匹配项。请注意,方括号需要转义,因为它们在正则表达式中具有特殊含义。

同样地,(?=# - finish - )位找到# - finish - 成功的匹配。

实际匹配由。*?执行,它会对所有内容执行惰性搜索。懒惰,这意味着尽快停止,这意味着第一次找到# - finish -

regexp中的其他参数'match'和'once'意味着返回找到的匹配,并且只返回一次。它作为字符数组返回,可以使用str2num将其转换为数字数组。尝试不使用str2num来查看正则表达式的作用。

你甚至可以更聪明地提取变量名称,但它可能变得相当复杂和混乱。您可以将问题分解为两个步骤:(1)在方括号之间找到变量,(2)在for循环中循环找到变量(将变量字符串转换为有效的matlab标识符)。