在MATLAB中更有效地读取外部文件

时间:2014-01-30 16:58:25

标签: matlab file batch-file external textscan

我遇到以下问题,我开发了一个代码来搜索包含数据的大型文件,这个过程变得太慢,甚至在某些计算机中它会占用所有可用的计算机资源。

nodo=str2num(get(handles.nodo,'string'));                                 
PATHNAME = uigetdir('', 'Selecciona el directorio donde están los bfins');
files = dir(fullfile(PATHNAME,'*.bfin') );                                
curr_folder=pwd;                                                          
cd(PATHNAME);                                                             
archivo={files.name}';                                                    
for i=1:numel(archivo)                                                    
        [fid{i}, errmsg]=fopen(files(i).name)                                 
        disp(errmsg);                                                         
        Datos{i}=textscan(fid{i}, '%s  %f %s %f %s %f ','Headerlines',2);     
        AllNodos{i}=Datos{1,i}{1,2};                                          
        AllTemp{i}=Datos{1,i}{1,4};                                           
end                                                                       
cd(curr_folder)                                                           
for i=1:size(AllNodos,2)                                                  
        sets{i}=cat(2, AllNodos{1,i}, AllTemp{1,i});                          
end                                                                       
for i=1:size(AllNodos,2)                                                  
        vectn{i}=AllNodos{1,i};                                               
        r{i}=find(vectn{i}==nodo);                                            
        Temps{i}=AllTemp{1,i}(r{i});                                          
end  
    %Write Excel File
[FileName, PathName] = uiputfile('*.xlsx', 'Escribe un archivo excel con las    temperaturas...')
savingas=fullfile(PathName,FileName);
a=archivo';
B=cat(1,a,Temps); 
xlswrite(savingas,[B])
e = actxserver ('Excel.Application'); %# open Activex server
ewb = e.Workbooks.Open(savingas); %# open file (enter full path!)
ewb.Worksheets.Item(1).Name = num2str(nodo); %# rename 1st sheet
ewb.Save %# save to the same file
ewb.Close(false)
e.Quit                                                              

代码真正做的是找到文件中字符串的位置,然后找到另一个变量(只是一个cntrl + f操作)并在excel表中重现它们,任何有关这方面的帮助都将受到赞赏。

EDIT ---- 非常感谢您的所有评论,我想出了以下代码,通过存储变量节省了大量不必要的时间:

    for i=1:num_archivo
   [fid(i), errmsg]=fopen(files(i).name)
   disp(errmsg);
   Datos=textscan(fid(i), '%s  %f %s %f','delimiter',',','HeaderLines',hl);
   AllNodos=Datos(1,2);
   AllTemp=Datos(1,4);
   for k=1:numel(nodo)
    r{i,k}=find(AllNodos{1,1}==nodo(k));
    Temps{i,k}=AllTemp{1,1}(r{i,k});
   end
   end

3 个答案:

答案 0 :(得分:1)

我的答案取决于数据集的大小。但我要做的第一个更改是将Datos{i}设置为Datos,因为您只在for循环中使用它。这样matlab就不必分配更多空间。

我要做的第二个更改是在第一个for循环中包含catfind函数,这样您也可以将Allnodos{i}替换为Allnodos并节省分配问题。

这应该有助于资源问题;如果文本扫描是限制因素,它可能无助于速度问题。在文本扫描之前和之后使用tictoc会告诉您它需要多长时间。

答案 1 :(得分:1)

textscan本身非常快,所以它可能正在吃CPU,但你不太可能在性能方面有所改进。但是,您似乎没有为您的单元阵列执行任何类型的预分配。这意味着Matlab可能会不断重新分配内存。使用cell创建所需大小的空单元格数组:

num_archivo = numel(archivo);
Datos = cell(1,num_archivo);
AllNodos = cell(1,num_archivo);
AllTemp = cell(1,num_archivo);
for i = 1:num_archivo
    ...
end
...

(虽然Datos可能不应该是@Lazarus指出的单元格。)你应该对setsvectn等其他循环做同样的事情。

我确定要做的另一件事是在您阅读files(i).name之后立即调用fclose(fid);,这样您就没有一堆打开的文件指针。此外,似乎没有理由将文件ID fid保存到单元阵列,因为您不在循环外使用它。即使你这样做,常规向量(用numel(archive)元素分配)也会更好。

答案 2 :(得分:1)

这取决于“大”文件的实际大小和数量。 使用探查器检查您的代码:

profile on;
<run your code>
profile viewer

我怀疑fopentextscan行是邪恶的......

一般来说,在阅读文件的任何事情上,瓶颈主要是磁盘i / o - 而不是CPU。 在这种情况下,除了并行处理之外你不能真正做很多事情,不幸的是在matlab中并不那么容易 - 如果你不愿意支付。