我正在寫一個matlab腳本,最終將文本行的行文本輸出到文件中。現在我只是不斷追加文字,如:經常在MATLAB中追加文本的最佳方式
Output = [];
Output = [Output NewText];
但我認爲這是低效的,因爲它必須每次創建一個新的矩陣。什麼會是更好的方法。
我無法打開文件,直到我準備好寫入所有文本,所以我不能只在輸出文件上使用fprintf。
我正在寫一個matlab腳本,最終將文本行的行文本輸出到文件中。現在我只是不斷追加文字,如:經常在MATLAB中追加文本的最佳方式
Output = [];
Output = [Output NewText];
但我認爲這是低效的,因爲它必須每次創建一個新的矩陣。什麼會是更好的方法。
我無法打開文件,直到我準備好寫入所有文本,所以我不能只在輸出文件上使用fprintf。
沒有明顯的最好的答案,至少對我來說。有些選項:
我的直覺表明履行順序將是:
但它並不明顯。
幸運的是,它很容易測試。下面的大型測試塊中包含了所有5個選項(以及一些測試包裝)的實現。我的計算機上的結果(一個不錯的電腦用SSD,結果可能會有所不同)低於(空間添加到代碼輸出格式):
-------------Start of file write speed tests. (nLines = 1)------------
Time for BaseLine operation: 0.001540 sec
Time for AutoAllocate operation: 0.001264 sec
Time for AutoAllocateCell operation: 0.003492 sec
Time for JavaStringBuilder operation: 0.001395 sec
Time for IncrementalWriteToFile operation: 0.001057 sec
-------------Start of file write speed tests. (nLines = 100)------------
Time for BaseLine operation: 0.011909 sec
Time for AutoAllocate operation: 0.014067 sec
Time for AutoAllocateCell operation: 0.011517 sec
Time for JavaStringBuilder operation: 0.021291 sec
Time for IncrementalWriteToFile operation: 0.016213 sec
-------------Start of file write speed tests. (nLines = 10000)------------
Time for BaseLine operation: 3.778957 sec
Time for AutoAllocate operation: 1.048480 sec
Time for AutoAllocateCell operation: 0.856269 sec
Time for JavaStringBuilder operation: 1.657038 sec
Time for IncrementalWriteToFile operation: 1.254080 sec
-------------Start of file write speed tests. (nLines = 100000)------------
Time for BaseLine operation: 358.312820 sec
Time for AutoAllocate operation: 10.349529 sec
Time for AutoAllocateCell operation: 8.539117 sec
Time for JavaStringBuilder operation: 16.520797 sec
Time for IncrementalWriteToFile operation: 12.259307 sec
所以,如果你使用的是「100的」線,它可能無關緊要;做任何工作。如果您知道性能問題,那麼我會使用「AutoAllocateCell」選項。這是非常簡單的代碼(見下文)。如果您沒有足夠的內存將整個文件一次存儲到內存中,我會使用「AutoAllocateCell」選項以及定期刷新文件。
測試代碼:
%Setup
cd(tempdir);
createLineLine = @(n, s) sprintf('[%04d] %s\n', n, s);
createRandomLine = @(n) createLineLine(n, char(randi([65 122],[1, round(rand*100)])));
for nLines = [1 100 10000 100000]
fprintf(1, ['-------------Start of file write speed tests. (nLines = ' num2str(nLines) ')------------\n']);
%% Baseline -----------------------------
strName = 'BaseLine';
rng(28375213)
tic;
str = [];
for ix = 1:nLines;
str = [str createRandomLine(ix)];
end
fid = fopen(['WriteTest_' strName],'w');
fprintf(fid, '%s', str);
fclose(fid);
fprintf(1, 'Time for %s operation: %f sec\n', strName, toc);
%% AutoAllocated string -----------------------------
strName = 'AutoAllocate';
rng(28375213)
tic;
str = blanks(256);
ixLastValid = 0;
for ix = 1:nLines;
strNewLine = createRandomLine(ix);
while (ixLastValid+length(strNewLine)) > length(str)
str(end*2) = ' '; %Doubles length of string
end
str(ixLastValid + (1:length(strNewLine))) = strNewLine;
ixLastValid = ixLastValid+length(strNewLine);
end
fid = fopen(['WriteTest_' strName],'w');
fprintf(fid, '%s', str(1:ixLastValid));
fclose(fid);
fprintf(1, 'Time for %s operation: %f sec\n', strName, toc);
%% AutoAllocated cell array -----------------------------
strName = 'AutoAllocateCell';
rng(28375213)
tic;
strs = cell(256,1);
ixLastValid = 0;
for ix = 1:nLines;
if ix>length(strs);
strs{end*2} = {}; %Doubles cell array size;
end
strs{ix} = createRandomLine(ix);
ixLastValid = ixLastValid + 1;
end
fid = fopen(['WriteTest_' strName],'w');
fprintf(fid, '%s', strs{1:ixLastValid});
fclose(fid);
fprintf(1, 'Time for %s operation: %f sec\n', strName, toc);
%% Java string builder -----------------------------
strName = 'JavaStringBuilder';
rng(28375213)
tic;
sBuilder = java.lang.StringBuilder;
for ix = 1:nLines;
sBuilder.append(createRandomLine(ix));
end
fid = fopen(['WriteTest_' strName],'w');
fprintf(fid, '%s', char(sBuilder.toString()));
fclose(fid);
fprintf(1, 'Time for %s operation: %f sec\n', strName, toc);
%% Incremental write to file -----------------------------
strName = 'IncrementalWriteToFile';
rng(28375213)
tic;
fid = fopen(['WriteTest_' strName],'w');
for ix = 1:nLines;
fprintf(fid, '%s', createRandomLine(ix));
end
fclose(fid);
fprintf(1, 'Time for %s operation: %f sec\n', strName, toc);
end
就像Oli在this question的評論中所說的,一個字符是一個行向量,所以任何適用於行向量的技術都適用於字符串。通過儘可能多地分配你認爲合理的數字,比如1000個字符,然後如果你打破了限制,加倍大小或者選擇你自己的算法。
下面是一個陳腐的例子:
testStrings = {['Is this a dagger which I see before me,' sprintf('\n') ],...
['The handle toward my hand? Come, let me clutch thee.' sprintf('\n') ],...
['I have thee not, and yet I see thee still.' sprintf('\n') ],...
['Art thou not, fatal vision, sensible' sprintf('\n') ],...
['To feeling as to sight? or art thou but' sprintf('\n') ],...
['A dagger of the mind, a false creation,' sprintf('\n') ],...
['Proceeding from the heat-oppressed brain?' sprintf('\n') ],...
['I see thee yet, in form as palpable' sprintf('\n') ],...
['As this which now I draw.' sprintf('\n') ],...
['Thou marshall''st me the way that I was going;' sprintf('\n') ],...
['And such an instrument I was to use.' sprintf('\n') ],...
['Mine eyes are made the fools o'' the other senses,' sprintf('\n') ],...
['Or else worth all the rest; I see thee still,' sprintf('\n') ],...
['And on thy blade and dudgeon gouts of blood,' sprintf('\n') ],...
['Which was not so before. There''s no such thing:' sprintf('\n') ],...
['It is the bloody business which informs' sprintf('\n') ],...
['Thus to mine eyes. Now o''er the one halfworld' sprintf('\n') ],...
['Nature seems dead, and wicked dreams abuse' sprintf('\n') ],...
['The curtain''d sleep; witchcraft celebrates' sprintf('\n') ],...
['Pale Hecate''s offerings, and wither''d murder,' sprintf('\n') ],...
['Alarum''d by his sentinel, the wolf,' sprintf('\n') ],...
['Whose howl''s his watch, thus with his stealthy pace.' sprintf('\n') ],...
['With Tarquin''s ravishing strides, towards his design' sprintf('\n') ],...
['Moves like a ghost. Thou sure and firm-set earth,' sprintf('\n') ],...
['Hear not my steps, which way they walk, for fear' sprintf('\n') ],...
'Thy very stones prate of my whereabout,'};
A = zeros(1,1000);
idx = 1;
for ii=1:length(testStrings)
str = testStrings{ii};
N = length(str);
eIdx = idx+N-1;
if(eIdx > length(A))
A = [ A zeros(1,length(A)*2) ];
end
A(idx:(idx+N-1)) = str;
idx = idx + N;
end
fprintf('%s',char(A))
你事先知道一個綁定上,將附加的「NewText」條目的數量? – Sai
[在Matlab中預分配字符串大小]的可能的重複(http://stackoverflow.com/questions/15398529/pre-allocating-the-string-size-in-matlab) – horchler
數百行不是很多。堅持正常的追加,直到你證明這是一個擔心的性能瓶頸。當涉及I/O時,這不太可能。 – Peter