Прочитать весь текстовый файл в переменную MATLAB одновременно - PullRequest
4 голосов
/ 21 августа 2010

Я хотел бы прочитать (довольно большой) файл журнала в строковую ячейку MATLAB за один шаг.Я использовал обычные:

s={};
fid = fopen('test.txt');
tline = fgetl(fid);
while ischar(tline)
   s=[s;tline];
   tline = fgetl(fid);
end

, но это только медленно.Я обнаружил, что

fid = fopen('test.txt');
x=fread(fid,'*char');

намного быстрее, но я получаю матрицу nx1 char, x.Я мог бы попытаться преобразовать x в строковую ячейку, но затем я попал в ад кодирования символов;Кажется, что разделитель строк равен \ n \ r, или 10 и 56 в ASCII (я посмотрел в конце первой строки), но эти два символа часто не следуют друг за другом и даже показываютиногда соло.

Существует ли простой быстрый способ прочитать файл ASCII в строковую ячейку за один шаг или преобразовать x в строковую ячейку?

Чтение с помощью fgetl:

Code                           Calls        Total Time      % Time
tline = lower(fgetl(fid));     903113       14.907 s        61.2%

Чтение через fread:

>> tic;for i=1:length(files), fid = open(files(i).name);x=fread(fid,'*char*1');fclose(fid); end; toc

Elapsed time is 0.208614 seconds.

Я проверил предварительное распределение, и это не помогает: (

files=dir('.');
tic
for i=1:length(files),   
    if files(i).isdir || isempty(strfind(files(i).name,'.log')), continue; end
    %# preassign s to some large cell array
    sizS = 50000;
    s=cell(sizS,1);

    lineCt = 1;
    fid = fopen(files(i).name);
    tline = fgetl(fid);
    while ischar(tline)
       s{lineCt} = tline;
       lineCt = lineCt + 1;
       %# grow s if necessary
       if lineCt > sizS
           s = [s;cell(sizS,1)];
           sizS = sizS + sizS;
       end
       tline = fgetl(fid);
    end
    %# remove empty entries in s
    s(lineCt:end) = [];
end
toc

Истекшее время составляет 12,741492 секунды.

Примерно в 10 раз быстрее, чем оригинал:

s = textscan(fid, '%s', 'Delimiter', '\n', 'whitespace', '', 'bufsize', files(i).bytes);

Мне пришлось установить 'whitespace' на '', чтобы сохранить начальные пробелы (которые мне нужны для разбора), и 'bufsize'к размеру файла (по умолчанию 4000 выдает ошибку переполнения буфера).

Ответы [ 4 ]

6 голосов
/ 21 августа 2010

Основная причина, по которой ваш первый пример медленный, заключается в том, что s растет в каждой итерации.Это означает воссоздание нового массива, копирование старых строк и добавление нового, что добавляет ненужные накладные расходы.

Чтобы ускорить процесс, вы можете предварительно назначить s

%# preassign s to some large cell array
s=cell(10000,1);
sizS = 10000;
lineCt = 1;
fid = fopen('test.txt');
tline = fgetl(fid);
while ischar(tline)
   s{lineCt} = tline;
   lineCt = lineCt + 1;
   %# grow s if necessary
   if lineCt > sizS
       s = [s;cell(10000,1)];
       sizS = sizS + 10000;
   end
   tline = fgetl(fid);
end
%# remove empty entries in s
s(lineCt:end) = [];

Вот небольшой пример того, что предварительное распределение может сделать для вас

>> tic,for i=1:100000,c{i}=i;end,toc
Elapsed time is 10.513190 seconds.

>> d = cell(100000,1);
>> tic,for i=1:100000,d{i}=i;end,toc
Elapsed time is 0.046177 seconds.
>> 

РЕДАКТИРОВАТЬ

В качестве альтернативы fgetl, вы можете использовать TEXTSCAN

fid = fopen('test.txt');
s = textscan(fid,'%s','Delimiter','\n');
s = s{1};

Это читает строки test.txtкак строка в массив ячеек s за один раз.

5 голосов
/ 07 июля 2012

Я обычно использую для этого urlread, например:

filename = 'test.txt';
urlname = ['file:///' fullfile(pwd,filename)];
try
    str = urlread(urlname);
catch err
    disp(err.message)
end

Переменная str содержит большой блок текста типа string (готов для работы с регулярным выражением).

1 голос
/ 20 февраля 2013

s = регулярное выражение ( fileread ('test.txt'), '( \ r \ n | \ n | \ r )', ' раскол ');

Пример работы с морскими ракушками в документации по регулярным выражениям Matlab приведен непосредственно.

1 голос
/ 21 августа 2010

Используйте функцию fgetl вместо fread. Для получения дополнительной информации, перейдите здесь

...