在Matlab中读取和处理大型文本文件

时间:2011-05-10 16:21:50

标签: file matlab io

我正在尝试将大文本文件(几百万行)读入Matlab。最初我使用的是importdata(file_name),这似乎是一个简洁的解决方案。但是我需要使用Matlab 7(是的,我知道它的旧版本),似乎不支持importdata。因此,我尝试了以下内容:

while ~feof(fid)    
    fline = fgetl(fid);
    fdata{1,lno} =  fline ;
    lno = lno + 1;
end

但这真的很慢。我猜它是因为它在每次迭代时调整数组大小。有没有更好的方法来做到这一点。请记住,输入数据的前20行是字符串类型数据,其余数据是3到6列十六进制值。

3 个答案:

答案 0 :(得分:5)

你将不得不做一些重塑,但另一个选择是你可以使用fread。 但正如所提到的,这基本上将您锁定为矩形导入。所以另一个选择是使用textscan。正如我在另一篇文章中提到的,我不是百分之百确定实施的时候,我所知道的是你没有“importdata()”

fid = fopen('textfile.txt')
Out  = textscan(fid,'%s','delimiter',sprintf('\n'));
fclose(fid)

通过使用文本扫描,您将能够获得每行的单元格数组,然后您可以根据需要进行操作。正如我在评论中所说的那样,线条长度是否相同并不重要。现在,您可以更快地解析单元阵列。但正如gnovice所提到的,他也确实有一个非常优雅的解决方案,你可能不得不关注内存需求。

如果你能避免它,你永远不想在matlab中使用的一件事就是循环结构。它们在C / C ++等方面很快,但在matlab中,它们是获取目标的最慢方式。

编辑:只是看了一下,看起来文本可以在版本7(R14)中逐字实现,所以如果那就是你拥有的,你应该很好用。

答案 1 :(得分:2)

我看到两个选项:

  1. 而不是每次每次增长,仅在必要时加上数组的大小。这大大减少了所需的重新分配数量。
  2. 做两次通过的方法。第一遍只计算行数,而不存储它们。第二遍实际上填充了数组(已预先分配到正确的大小)。

答案 2 :(得分:2)

一种解决方案是将文件的全部内容作为带有FSCANF的字符串读取,使用MAT2CELL将字符串拆分为出现换行符的点的单个单元格,删除多余的空格在STRTRIM的末尾,然后根据需要处理每个单元格中的字符串数据。例如,使用此示例文本文件'junk.txt'

hi
hello
1 2 3
FF 00 FF
12 A6 22 20 20 20
FF FF FF

以下代码将每行放在单元格数组cellData的单元格中:

>> fid = fopen('junk.txt','r');
>> strData = fscanf(fid,'%c');
>> fclose(fid);
>> nCharPerLine = diff([0 find(strData == char(10)) numel(strData)]);
>> cellData = strtrim(mat2cell(strData,1,nCharPerLine))

cellData = 

    'hi'    'hello'    '1 2 3'    'FF 00 FF'    '12 A6 22 20 20 20'    'FF FF FF'

现在,如果要将所有十六进制数据(我的示例数据文件中的第3行到第6行)从字符串转换为数字向量,您可以使用CELLFUNSSCANF,如下所示:< / p>

>> cellData(3:end) = cellfun(@(s) {sscanf(s,'%x',[1 inf])},cellData(3:end));
>> cellData{3:end}    %# Display contents

ans =

     1     2     3

ans =

   255     0   255

ans =

    18   166    34    32    32    32

ans =

   255   255   255

注意:由于您正在处理此类大型数组,因此您必须注意变量的amount of memory being used。上述解决方案是矢量化的,但可能占用大量内存。在创建strData时,您可能需要覆盖clear大变量,例如cellData。或者,您可以循环遍历nCharPerLine中的元素,并将较大字符串strData的每个段单独处理为您需要的向量,您可以预先分配,因为您知道如何您拥有的许多数据行(即nDataLines = numel(nCharPerLine)-nHeaderLines;)。