2014-02-05 5 views
1

Я пытаюсь обработать вывод команды system('./foo'). Если я напрямую перенаправляю вывод в файл с system('./foo > output') и читаю файл по адресу dlmread в MATLAB, он отлично работает, но я стараюсь избегать записи огромного ASCII-файла (около 1e7 строк) на жесткий диск каждый раз, когда я это делаю ,Сплит больших строк по разделителям

Так что я хочу иметь дело с выходом напрямую, читая его в огромную строку и разбивая строку. Он отлично работает для небольших файлов:

[a,b] = system('./foo') 
b=strsplit(b); 
cellfun(@str2num, bb); 
b=cellfun(@str2num, b(1:end),'UniformOutput',0); 
b=cell2mat(b); 

К сожалению, это потребляет уже на этапе strsplit работы слишком много памяти, так что MATLAB получает убиты OOM убийцей. я нашел альтернативу:

b=textscan(b,'%s','delimiter',' ','multipleDelimsAsOne',1); 

Но он также потребляет слишком много памяти.

Может ли кто-нибудь помочь мне с лучшей идеей разделить эту строку чисел и прочитать ее в матрицу или вообще как избежать записи вывода команды в файл на жестком диске?

Редактировать: (Я пишу здесь, потому что в комментариях недостаточно места ...) @ MZimmerman6 Я попробовал сейчас версию dlmread с предварительным размещением и без вашего предложения, а также я понял это : На самом деле цикл намного медленнее, чем dlmread.

clear all 
close all 
tic 
ttags1=dlmread('tmp.txt',' ',1,3); 

toc 

clear all 

tic 
[~,result]=system('perl -e ''while(<>){};print$.,"\n"'' tmp.txt'); 
numLines1=str2double(result); 
ttags=zeros(numLines1,1); 
ttags=dlmread('tmp.txt',' ',1,3); 

toc 

clear all 

tic 
fid = fopen('tmp.txt'); 
count = 1; 
[~,result]=system('perl -e ''while(<>){};print$.,"\n"'' tmp.txt'); 
numLines1=str2double(result); 
temp = cell(numLines1,1); 
for i = 1:numLines1 
    tline = fgetl(fid); 
    if ischar(tline) 
     vals = textscan(tline,'%f','delimiter',','); 
     temp{i} = transpose(vals{1}); 
    end 
end 
fclose(fid); 
temp = cell2mat(temp); 

toc 

Результат:

Elapsed time is 19.762470 seconds. 
Elapsed time is 21.546079 seconds. 
Elapsed time is 796.755343 seconds. 

Спасибо & С наилучшими пожеланиями

Я делаю что-то не так?

ответ

1

Вам не следует пытаться прочитать весь файл в памяти, так как это может быть очень тяжело. Я бы рекомендовал читать файл по строкам и обрабатывать каждый отдельно, а затем хранить результаты в массиве ячеек. После этого вы можете преобразовать это в нормальную матрицу.

Первое, что я могу сделать, это создать небольшой скрипт Perl для подсчета количества строк в файле, который вы читаете, поэтому вы можете предварительно выделить память для данных. Вызов этого файла countlines.pl. Информация, собранная из here

Perl - Countlines.pl

while (<>) {}; 
print $.,"\n"; 

Этот файл будет только две линии, но быстро подсчитать общее количество строк в файле.

Затем вы можете использовать результат этого файла для предварительного выделения, а затем провести разбор строки. Я использовал в своем тестировании простой файл с разделенной запятой, поэтому вы можете настроить textscan для обработки вещей по своему усмотрению.

MATLAB Script

% get number of lines in data file 
numLines = str2double(perl('countlines.pl','text.txt')); 
fid = fopen('text.txt'); 
count = 1; 
temp = cell(numLines,1); 
for i = 1:numLines 
    tline = fgetl(fid); 
    if ischar(tline) 
     vals = textscan(tline,'%f','delimiter',','); 
     temp{i} = transpose(vals{1}); 
    end 
end 
fclose(fid); 
temp = cell2mat(temp); 

Это должно работать достаточно быстро в зависимости от размера файла, и делать то, что вы хотите.Конечно, вы можете отредактировать, как синтаксический анализ выполняется внутри цикла, но это должно быть хорошей отправной точкой.

Обратите внимание на будущее, не пытайтесь читать большое количество материала в памяти, если оно не является полностью необходимым

+0

+1. Другие способы быстрого подсчета строк [здесь] (http://stackoverflow.com/questions/12176519/is-there-a-way-in-matlab-to-determine-the-number-of-lines-in-a- файл-без петли). – horchler

+0

И нельзя использовать что-то вроде следующего: '[~, result] = system ('perl -e' 'while (<>) {}; print $.," \ N "' 'text.txt') ; 'numLines = str2double (result);'? Или использование файла делает его быстрее или это просто не кросс-платформенный? – horchler

+0

Хорошо, Спасибо за ваши ответы! Я действительно проверю, могу ли я сразу загрузить весь файл. Мне просто интересно, почему вы использовали массив ячеек для чтения данных? Это лучше, чем распределение пространства с нулями (numLines, 1), если я знаю, что хочу читать числа? Еще раз спасибо, тоже horchler! – Mechanix

Смежные вопросы