通过分隔符拆分大字符串

时间:2014-02-05 20:14:56

标签: string matlab large-data

我正在尝试处理system('./foo')命令的输出。如果我直接将输出重定向到system('./foo > output')的文件并通过dlmread将文件读入MATLAB,它可以正常工作,但我试图避免写一个巨大的ASCII文件(大约1e7行)每次我这样做的硬盘。

所以我想通过将输出读入一个巨大的字符串并拆分字符串来直接处理输出。它适用于小文件:

[a,b] = system('./foo')
b=strsplit(b);
cellfun(@str2num, bb);
b=cellfun(@str2num, b(1:end),'UniformOutput',0);
b=cell2mat(b);

不幸的是,这已经在strsplit操作步骤消耗了太多内存,因此MATLAB被OOM杀手杀死了。 我找到了替代方案:

b=textscan(b,'%s','delimiter',' ','multipleDelimsAsOne',1);

但它也消耗了太多的内存。

有人可以帮助我更好地了解如何拆分数字串并将其读入矩阵或一般如何避免将命令输出写入硬盘上的文件?

编辑:(我在这里写,因为在评论中空间不够......) @ MZimmerman6我现在尝试了dlmread的版本,无论是否有预先分配和你的建议以及我理解它: 事实上,循环比dlmread慢得多。

clear all
close all
tic 
ttags1=dlmread('tmp.txt',' ',1,3);

toc

clear all

tic
[~,result]=system('perl -e ''while(<>){};print$.,"\n"'' tmp.txt');
numLines1=str2double(result);
ttags=zeros(numLines1,1);
ttags=dlmread('tmp.txt',' ',1,3);

toc

clear all

tic 
fid = fopen('tmp.txt');
count = 1;
[~,result]=system('perl -e ''while(<>){};print$.,"\n"'' tmp.txt');
numLines1=str2double(result);
temp = cell(numLines1,1);
for i = 1:numLines1
    tline = fgetl(fid);
    if ischar(tline)
        vals = textscan(tline,'%f','delimiter',',');
        temp{i} = transpose(vals{1});
    end
end
fclose(fid);
temp  = cell2mat(temp);

 toc

结果是:

Elapsed time is 19.762470 seconds.
Elapsed time is 21.546079 seconds.
Elapsed time is 796.755343 seconds.

谢谢你&amp;最诚挚的问候

我做错了吗?

1 个答案:

答案 0 :(得分:1)

您不应该尝试将整个文件读入内存,因为这可能会占用大量内存。我建议逐行读取文件,然后单独处理,然后将结果存储到单元格数组中。然后,您可以在解析完成后将其转换为普通矩阵。

我能做的第一件事是创建一个小的Perl脚本来计算你正在读取的文件中的行数,这样你就可以为数据预先分配内存。请将此文件称为countlines.pl。从here

收集的信息

Perl - Countlines.pl

 while (<>) {};
 print $.,"\n";

此文件只有两行,但会快速计算文件中的总行数。

然后,您可以使用此文件的结果进行预分配,然后逐行解析。我在测试中使用了一个简单的逗号分隔文件,因此您可以根据需要调整文本扫描来处理事物。

MATLAB脚本

% get number of lines in data file
numLines = str2double(perl('countlines.pl','text.txt'));
fid = fopen('text.txt');
count = 1;
temp = cell(numLines,1);
for i = 1:numLines
    tline = fgetl(fid);
    if ischar(tline)
        vals = textscan(tline,'%f','delimiter',',');
        temp{i} = transpose(vals{1});
    end
end
fclose(fid);
temp  = cell2mat(temp);

这应该相对较快地运行,具体取决于您的文件大小,并执行您想要的操作。当然你可以编辑在循环中完成解析的方式,但这应该是一个很好的起点。

注意将来,如果不是非常必要,请不要尝试将大量内容读入内存