读取文本文件并将数据分成不同的列和MATLAB中的不同表

时间:2016-01-28 16:24:49

标签: matlab text file-io text-parsing

我有一个巨大的文本文件,需要在MATLAB中读取和处理。某些点上的此文件包含指示已启动新数据系列的文本。 我在这里搜索过,但无法找到任何简单的解决方案。

所以我想要做的是读取文件中的数据,将数据放在三个不同列的表中,当它找到文本时,它应该创建一个新表。它应该重复此过程,直到扫描整个文档。

这就是文件的样子:

    time    V(A,B)  I(R1)
    Step Information: X=1  (Run: 1/11)
    0.000000000000000e+000  -2.680148e-016  0.000000e+00
    9.843925313007988e-012  -4.753470e-006  2.216314e-011
    1.000052605772457e-011  -4.835427e-006  2.552497e-011
    1.031372754715773e-011  -4.999340e-006  -3.042096e-012
    1.094013052602406e-011  -5.327165e-006  -1.206968e-011
    Step Information: X=1  (Run: 2/11)
    0.000000000000000e+000  -2.680148e-016  0.000000e+000
    9.843925313007988e-012  -4.753470e-006  2.216314e-011
    1.000052605772457e-011  -4.835427e-006  2.552497e-011
    1.031372754715773e-011  -4.999340e-006  -3.042096e-012
    1.094013052602406e-011  -5.327165e-006  -1.206968e-011

2 个答案:

答案 0 :(得分:3)

一种相当粗略的方法是逐行读取文件并检查该行是否包含三个数字。如果是,则将其附加到临时矩阵。当您最终到达不包含三个数字的行时,将此矩阵作为元素追加到单元格数组中,清除临时矩阵并继续。

假设文件存储在'file.txt'

中,这样的操作就可以了
%// Open the file
f = fopen('file.txt', 'r');

%// Initialize empty cell array
data = {};

%// Initialize temporary matrix
temp = [];

%// Loop over the file...
while true
    %// Get a line from the file
    line = fgetl(f);

    %// If we reach the end of the file, get out
    if line == -1
        %// Last check before we break
        %// Check if the temporary matrix isn't empty and add
        if ~isempty(temp)
            data = [data; temp];
        end
        break; 
    end

    %// Else, check to see if this line contains three numbers
    numbers = textscan(line, '%f %f %f');

    %// If this line doesn't consist of three numbers...
    if all(cellfun(@isempty, numbers))
        %// If the temporary matrix is empty, skip
        if isempty(temp)
            continue;
        end
        %// Concatenate to cell array
        data = [data; temp];
        %// Reset temporary matrix
        temp = [];
    %// If this does, then create a row vector and concatenate
    else
        temp = [temp; numbers{:}];
    end
end

%// Close the file
fclose(f);

代码是不言自明的,但让我们进入它,以确保你知道发生了什么。首先使用fopen打开文件以获取文件的“指针”,然后初始化包含矩阵的单元格数组以及在标题信息之间读取矩阵时使用的临时矩阵。在我们简单地遍历文件的每一行之后,我们可以使用我们创建的文件指针使用fgetl获取一行。然后我们检查是否已到达文件的末尾,如果有,我们检查一下临时矩阵中是否有任何数值数据。如果是这样,将其添加到我们的单元格数组中,然后最终退出循环。我们使用fclose来关闭文件并进行清理。

现在,检查后的操作核心是以下内容。我们使用textscan并搜索由空格分隔的三个数字。这是使用'%f %f %f'格式说明符完成的。如果您成功使用数字,这应该为您提供三个元素的单元格数组。如果这是正确的,则将此单元格元素数组转换为一行数字,并将其连接到临时矩阵中。执行temp = [temp; numbers{:}];有助于此连接。简单地说,我将每个数字拼凑在一起并水平连接它们以创建一行数字。然后我接受这一行并将其连接为临时矩阵中的另一行。

如果我们最终到达所有文本的行,这将使textscan找到的单元格数组中的所有三个元素都为空。这就是allcellfun电话的目的。我们搜索单元格中的每个元素,看它是否为空。如果每个元素都为空,则这是一行文本。如果出现这种情况,只需使用临时矩阵并将其作为新条目添加到单元格数组中。然后,您将重置临时矩阵并重新启动逻辑。

但是,我们还必须考虑到可能有多行由文本组成。这就是使用if在第一个if块内添加all语句的内容。如果我们在前一行文本之前有一行额外的文本,那么临时值的值仍应为空,因此在尝试连接临时矩阵之前,应检查是否为空。如果它是空的,不要打扰,只是继续。

运行此代码后,我得到了以下数据矩阵:

>> format long g
>> celldisp(data)


data{1} =

                         0             -2.680148e-16                         0
      9.84392531300799e-12              -4.75347e-06              2.216314e-11
      1.00005260577246e-11             -4.835427e-06              2.552497e-11
      1.03137275471577e-11              -4.99934e-06             -3.042096e-12
      1.09401305260241e-11             -5.327165e-06             -1.206968e-11



data{2} =

                         0             -2.680148e-16                         0
      9.84392531300799e-12              -4.75347e-06              2.216314e-11
      1.00005260577246e-11             -4.835427e-06              2.552497e-11
      1.03137275471577e-11              -4.99934e-06             -3.042096e-12
      1.09401305260241e-11             -5.327165e-06             -1.206968e-11

要访问特定的“表格”,请执行data{ii},其中ii是您要访问的表格,该表格是从文本文件中自上而下读取的。

答案 1 :(得分:0)

最通用的方法是使用textscan逐行阅读。如果你想加快这个过程,你可以先进行虚拟读取: 即。循环遍历所有行而不存储数据,并确定哪些行是文本行,哪些行是数字,为每个行记录快速行数。 然后,您可以获得有关数据的足够信息,以便快速运行数组。这将大大加快将数据大量存储在新阵列中所需的时间。 你的第二个循环是实际将数据读入数组的循环。您现在应该知道要跳过哪些行。如果您愿意,也可以在数据单元中预先分配数组。

fid = fopen('file.txt','r');
data = {};
nlines = [];

% now start the loop
k=0;  % counter for data sets

while ~feof(fid)

    line = fgetl(fid);

    % check if is data or text
    if all(ismember(line,' 0123456789+.')) % is it data
        nlines(k) = nlines(k)+1;
    else                                   %is it text
        k=k+1;
        nlines(k) = 0;
    end
end

frewind(fid);  % go back to start of file

% You could preallocate the data array here if you wished

% now get the data
for aa = 1 : length(nlines)
    if nlines(aa)==0;
        continue
    end
    textscan(fid,'%s\r\n',1); % skip textline
    data{aa} = textscan(fid,'%f%f%f\r\n',nlines(k));
end