2013-06-28 73 views
3

我正在寫一個matlab腳本,最終將文本行的行文本輸出到文件中。現在我只是不斷追加文字,如:經常在MATLAB中追加文本的最佳方式

Output = []; 
Output = [Output NewText]; 

但我認爲這是低效的,因爲它必須每次創建一個新的矩陣。什麼會是更好的方法。

我無法打開文件,直到我準備好寫入所有文本,所以我不能只在輸出文件上使用fprintf。

+1

你事先知道一個綁定上,將附加的「NewText」條目的數量? – Sai

+1

[在Matlab中預分配字符串大小]的可能的重複(http://stackoverflow.com/questions/15398529/pre-allocating-the-string-size-in-matlab) – horchler

+1

數百行不是很多。堅持正常的追加,直到你證明這是一個擔心的性能瓶頸。當涉及I/O時,這不太可能。 – Peter

回答

5

沒有明顯的最好的答案,至少對我來說。有些選項:

  1. 你在做什麼,逐漸追加到一個字符串,每次迭代
  2. 智能化越來越多的積累字符串,以減少重新分配的
  3. 的數量(@macduff答案的核心)使用字符串的單元數組,並智能地重新分配。 (我很確定)這隻會強制重新分配指針,而不是完全重新分配字符串內容。
  4. 使用一些Java魔法來處理字符串累積。 Java庫有許多有用的功能(比如StringBuilder類),但是Matlab-Java接口很慢。
  5. 增量直接寫入文件(我知道你考慮的問題刪除這一點,但它仍然是一個有用的基準。)

我的直覺表明履行順序將是:

  • 最佳:(2或3)
  • 中等:(4或5)
  • 最壞:(1)

但它並不明顯。

幸運的是,它很容易測試。下面的大型測試塊中包含了所有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 
1

就像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)) 
相關問題