我对MATLAB的textscan
有疑问。我有一个非常多的列的文件,以及1-32行(与#col相比非常小)的文件。这是一个简单的例子:
Test1 1 2 3 4 5
Test2 6 7 8 9 10
提前知道列数,提前知道第一个且唯一开始一行的字符串的长度。我在第一行读取并计算列数,并构建实际格式字符串以在文件的其余部分中读取,如下所示:
function output = parseFile(filename)
%% Calculate Number of Samples
% Reads in first line
tic
fid = fopen(filename);
line = fgetl(fid);
fclose(fid);
firstLine = textscan(line, '%s', 'CollectOutput', true);
numSamples = size(firstLine{1},1) - 1;
toc
%% Parse File
tic
fid = fopen(filename);
format = ['%s ' repmat('%f', [1 numSamples]) '%*[^\n\r]'];
fileData = textscan(fid, format, 'CollectOutput', true);
fclose(fid);
toc
%% Format Output
output.names = cell2mat(fileData{1});
output.values = fileData{2};
end % end function
我选了几个例子,每次我得到以下内容:说我有一个包含100,000列和3行的文件。 tic
/ toc
告诉我第一行读取在.16秒内完成。然后,当我构建格式字符串并读取整个文档时,它将在9秒内完成。为什么第一行作为%s
读入时如此快速地读取,但下次我读取整个文件(仅多+2行)时需要更长时间?是因为更复杂的format
字符串,我第二次解析文件?将整个文件解析为空格分隔的字符串然后执行后处理(例如:str2double
)以获得我的双打矩阵是否有意义?
编辑:澄清文件格式的具体细节:
(string of unknown length)(1 space)(-123.001)(1 space)(41.341)(1 space)...
...
所以数字不 int
,而且它们是正面/负面的。
注意:我实际上很困惑的是,为什么textscan能够非常快速地读取文件的第一行,而接下来的两行比第一行长多。
答案 0 :(得分:1)
将字符串转换为数字的常用技巧是从字符串中删除double('0')
。此外,这种方式比str2double
快得多。例如,运行此代码:
% Using -double('0')
tic, for i=1:1e5; aux='9'-48; end, toc
% Using str2double()
tic, for i=1:1e5; str2double('9'); end, toc
% Using str2num()
tic, for i=1:1e5; str2num('9'); end, toc
我明白了:
Elapsed time is 0.000480 seconds.
Elapsed time is 2.445741 seconds.
Elapsed time is 2.524999 seconds.
因此,你可以构造一个解析每一行的函数(我猜这个函数可以更优化):
function num = parseText(str)
strCell = strsplit(str,' ');
strNum = cellfun(@(s) s-48, strCell(2:end),'UniformOutput', false);
nNum = numel(strNum); num = zeros(1,nNum);
for idxNum=1:nNum,
num(idxNum) = strNum{idxNum}*10.^(length(strNum{idxNum})-1:-1:0).';
end
end
如果您尝试一行,结果很好:
str = 'Test1 0 1 2 3 4 5 10';
num = parseText(str);
如果您尝试多行,它似乎也很好:
% Create text
L = 10; str = cell(L,1);
for idx1=1:L,
strAux = []; for idx2=1:randi(10), strAux = [strAux,' ',num2str(randi(10))]; end
str{idx1} = ['Test',num2str(idx1),strAux];
end
% Parse text
num = cell(L,1);
for idx=1:L,
num{idx} = parseText(str{idx});
end