1

我有一个关于 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 行的文件。/ s 告诉我第一行读取在 0.16 秒内完成tictoc然后,当我构建格式字符串并阅读整个文档时,它会在 9 秒内完成。为什么读入时第一行%s读入如此之快,但下一次我读取整个文件(仅多 2 行)时却需要更长的时间?是因为format我第二次解析文件时使用了更复杂的字符串吗?将整个文件解析为空格分隔的字符串然后执行后处理(例如:)str2double以获取我的双精度矩阵是否有意义?

编辑:澄清文件格式的细节:

(string of unknown length)(1 space)(-123.001)(1 space)(41.341)(1 space)...
...

所以数字不是 int,它们是正/负。

注意:我基本上感到困惑的是,为什么 textscan 能够非常快速地读取文件的第一行,而接下来的两行比第一行花费的时间长得多。

4

1 回答 1

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
于 2014-02-27T10:23:48.383 回答