【发布时间】:2011-04-02 00:56:00
【问题描述】:
我想一步将一个(相当大的)日志文件读入 MATLAB 字符串单元格。我用的是平常的:
s={};
fid = fopen('test.txt');
tline = fgetl(fid);
while ischar(tline)
s=[s;tline];
tline = fgetl(fid);
end
但这只是很慢。我发现了
fid = fopen('test.txt');
x=fread(fid,'*char');
更快,但我得到了一个 nx1 字符矩阵 x。我可以尝试将x 转换为字符串单元格,但随后我进入了字符编码地狱;行分隔符似乎是 \n\r,或 ASCII 中的 10 和 56(我已经查看了第一行的末尾),但这两个字符通常不会相互跟随,有时甚至会单独出现。
有没有一种简单快速的方法可以一步将 ASCII 文件读入字符串单元格,或将x 转换为字符串单元格?
通过 fgetl 读取:
Code Calls Total Time % Time
tline = lower(fgetl(fid)); 903113 14.907 s 61.2%
通过 fread 阅读:
>> tic;for i=1:length(files), fid = open(files(i).name);x=fread(fid,'*char*1');fclose(fid); end; toc
Elapsed time is 0.208614 seconds.
我已经测试了预分配,但它没有帮助:(
files=dir('.');
tic
for i=1:length(files),
if files(i).isdir || isempty(strfind(files(i).name,'.log')), continue; end
%# preassign s to some large cell array
sizS = 50000;
s=cell(sizS,1);
lineCt = 1;
fid = fopen(files(i).name);
tline = fgetl(fid);
while ischar(tline)
s{lineCt} = tline;
lineCt = lineCt + 1;
%# grow s if necessary
if lineCt > sizS
s = [s;cell(sizS,1)];
sizS = sizS + sizS;
end
tline = fgetl(fid);
end
%# remove empty entries in s
s(lineCt:end) = [];
end
toc
经过的时间是 12.741492 秒。
比原来快大约 10 倍:
s = textscan(fid, '%s', 'Delimiter', '\n', 'whitespace', '', 'bufsize', files(i).bytes);
我必须将 'whitespace' 设置为 '' 以保留前导空格(我需要解析),并将 'bufsize' 设置为文件大小(默认 4000 引发缓冲区溢出错误)。
【问题讨论】:
-
好吧,你获得了 2 秒 :)。无论如何,Matlab 中的低级 fileIO 函数具有惊人的大开销。我在演示 SSD RAID 时了解到这一点,发现速度几乎没有任何提升。
标签: file matlab file-io ascii cell