Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在MATLAB中经常附加文本的最佳方法_Matlab - Fatal编程技术网

在MATLAB中经常附加文本的最佳方法

在MATLAB中经常附加文本的最佳方法,matlab,Matlab,我正在编写一个matlab脚本,最终将成行的文本输出到一个文件中。现在,我只是不断添加文本,如: Output = []; Output = [Output NewText]; 但我认为这是低效的,因为它每次都必须创建一个新的矩阵。还有什么更好的办法 在准备好写入所有文本之前,我无法打开该文件,因此我不能在输出文件上继续使用fprintf。正如Oli在对的评论中所说,字符是行向量,因此任何适用于行向量的技术都适用于字符串。从分配你认为合理的数量开始,比如1000个字符,然后如果你超出了限制,就

我正在编写一个matlab脚本,最终将成行的文本输出到一个文件中。现在,我只是不断添加文本,如:

Output = [];
Output = [Output NewText];
但我认为这是低效的,因为它每次都必须创建一个新的矩阵。还有什么更好的办法


在准备好写入所有文本之前,我无法打开该文件,因此我不能在输出文件上继续使用fprintf。

正如Oli在对的评论中所说,字符是行向量,因此任何适用于行向量的技术都适用于字符串。从分配你认为合理的数量开始,比如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))

至少对我来说,没有一个明显的最佳答案。有些选择是:

  • 确切地说,您正在做什么,每次迭代都递增地附加到字符串
  • 智能地增加累积字符串以减少重新分配的数量(@macduff答案的核心)
  • 使用字符串的单元格数组,并智能地重新分配该字符串。(我很确定)这只是强制重新分配指针,而不是完全重新分配字符串内容
  • 使用一些Java魔术来处理字符串累积。Java库有许多有用的特性(如StringBuilder类),但MatlabJava接口速度较慢
  • 以增量方式直接写入文件(我知道您在问题中已将其从考虑范围中删除,但它仍然是一个有用的基线。)
  • 我的直觉表明,绩效顺序是:

    • 最佳:(2或3)
    • 中期:(4或5)
    • 最差:(1)
    但这并不明显

    幸运的是,它很容易测试。所有5个选项(加上一些测试包装)的实现都包含在下面的大型测试块中。我的计算机(一台带SSD的非常好的计算机,结果可能会有所不同)上的结果如下(在代码输出中添加空格以进行格式化):

    所以,如果你用的是“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
    

    您是否预先知道将要追加的“NewText”条目的数量界限?数百行的可能重复项并不多。坚持使用普通的附加,直到您证明这是一个需要担心的性能瓶颈。当涉及I/O时,不太可能。
    %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