Импорт текстовых файлов с низкоуровневым вводом-выводом

Панорама

Низкоуровневые функции ввода-вывода файлов позволяют максимально контролировать чтение или запись данных в файл. Однако эти функции требуют, чтобы вы указали более подробную информацию о своем файле, чем более простые в использовании высокоуровневые функции, такие как importdata. Для получения дополнительной информации о высокоуровневых функциях, которые читают текстовые файлы, см. Текстовые файлы Импорта.

Если высокоуровневые функции не могут импортировать ваши данные, используйте одно из следующего:

Для получения дополнительной информации см.:

Примечание

Низкоуровневые функции ввода-вывода файлов основаны на функциях в библиотеке ANSI® Standard C Library. Однако<sup class="" contenteditable="">However, MATLAB®</sup>&nbsp; включает векторизованные версии функций для чтения и записи данных в массив с минимальными циклами управления.

Чтение данных в форматированный шаблон

Импортировать текстовые файлы что importdata и textscan не может считать, рассмотреть использование fscanf. fscanf функция требует, чтобы вы описали формат своего файла, но включает много опций для этого описания формата.

Например, создайте текстовый файл mymeas.dat как показано. Данные в mymeas.dat включает повторенные наборы времен, дат и измерений. Текст заголовка включает количество наборов измерений, N:

Measurement Data
N=3

12:00:00
01-Jan-1977
4.21  6.55  6.78  6.55
9.15  0.35  7.57  NaN
7.92  8.49  7.43  7.06
9.59  9.33  3.92  0.31
09:10:02
23-Aug-1990
2.76  6.94  4.38  1.86
0.46  3.17  NaN   4.89
0.97  9.50  7.65  4.45
8.23  0.34  7.95  6.46
15:03:40
15-Apr-2003
7.09  6.55  9.59  7.51
7.54  1.62  3.40  2.55
NaN   1.19  5.85  5.05
6.79  4.98  2.23  6.99

Открытие файла

Как с любой из низкоуровневых функций ввода-вывода, перед чтением, открывают файл с fopen, и получите идентификатор файла. По умолчанию, fopen открывает файлы для доступа для чтения, с разрешением 'r'.

Когда вы закончили обрабатывать файл, закрываете его с fclose(fid).

Описание данных

Опишите данные в файле со спецификаторами формата, такими как '%s' для текста, '%d' для целого числа или '%f' для числа с плавающей запятой. (Для полного списка спецификаторов смотрите fscanf страница с описанием.)

Чтобы пропустить буквенные символы в файле, включайте их в описание формата. Чтобы пропустить поле данных, используйте звездочку ('*') в спецификаторе.

Например, рассмотрите линии заголовка mymeas.dat:

Measurement Data   % skip the first 2 words, go to next line:  %*s %*s\n
N=3                % ignore 'N=', read integer:  N=%d\n
                   % go to next line:  \n
12:00:00
01-Jan-1977
4.21  6.55  6.78  6.55
...

Считать заголовки и возвратить одно значение для N:

N = fscanf(fid, '%*s %*s\nN=%d\n\n', 1);

Определение количества значений, чтобы читать

По умолчанию, fscanf повторно применяет ваше описание формата, пока оно не может совпадать с описанием к данным, или оно достигает конца файла.

Опционально, задайте количество значений, чтобы читать, так, чтобы fscanf не пытается считать целый файл. Например, в mymeas.dat, каждый набор измерений включает постоянное число строк и столбцов:

measrows = 4;
meascols = 4;
meas  = fscanf(fid, '%f', [measrows, meascols])';

Создание переменных в рабочей области

Существует несколько способов сохранить mymeas.dat в рабочем пространстве MATLAB. В этом случае считайте значения в структуру. Каждый элемент структуры имеет три поля: mtime, mdate, и meas.

Примечание

fscanf массивы заливок с числовыми значениями в порядке следования столбцов. Чтобы заставить выходной массив совпадать с ориентацией числовых данных в файле, транспонируйте массив.

filename = 'mymeas.dat';
measrows = 4;
meascols = 4;

% open the file
fid = fopen(filename);

% read the file headers, find N (one value)
N = fscanf(fid, '%*s %*s\nN=%d\n\n', 1);

% read each set of measurements
for n = 1:N
    mystruct(n).mtime = fscanf(fid, '%s', 1);
    mystruct(n).mdate = fscanf(fid, '%s', 1);

    % fscanf fills the array in column order,
    % so transpose the results
    mystruct(n).meas  = ...
      fscanf(fid, '%f', [measrows, meascols])';
end

% close the file
fclose(fid);

Построчное чтение данных

MATLAB обеспечивает две функции, которые читают строки из файлов и хранят их как векторы символов: fgetl и fgets. fgets функция копирует строку наряду с символом новой строки к выходу, но fgetl не делает.

Следующий пример использует fgetl считать целый файл одна линия за один раз. Функциональный litcount определяет ли данная последовательность символов (literal) появляется в каждой линии. Если это так, функция печатает всю строку, столько раз, сколько литерал появляется в строке.

function y = litcount(filename, literal)
% Count the number of times a given literal appears in each line.

fid = fopen(filename);
y = 0;
tline = fgetl(fid);
while ischar(tline)
   matches = strfind(tline, literal);
   num = length(matches);
   if num > 0
      y = y + num;
      fprintf(1,'%d:%s\n',num,tline);
   end
   tline = fgetl(fid);
end
fclose(fid);

Создайте файл входных данных под названием badpoem:

Oranges and lemons,
Pineapples and tea.
Orangutans and monkeys,
Dragonflys or fleas.

Узнать сколько раз 'an' появляется в этом файле, вызовите litcount:

litcount('badpoem','an')

Это возвращается:

2: Oranges and lemons,
1: Pineapples and tea.
3: Orangutans and monkeys,
ans =
     6

Проверка конца файла (EOF)

Когда вы читаете фрагмент своих данных за один раз, можно использовать feof проверять, достигли ли вы конца файла. feof возвращает значение 1 когда указатель файла в конце файла. В противном случае это возвращает 0.

Примечание

Открытие пустого файла не перемещает индикатор позиции в файле в конец файла. Операции чтения и fseek и frewind функции, переместите индикатор позиции в файле.

Тестирование на EOF с feof

Когда вы используете textscanfscanf, или fread чтобы считать фрагменты данных за один раз, используйте feof проверять, достигли ли вы конца файла.

Например, предположите что гипотетический файл mymeas.dat имеет следующую форму, без информации о количестве наборов измерения. Считайте данные в структуру с полями для mtime, mdate, и meas:

12:00:00
01-Jan-1977
4.21  6.55  6.78  6.55
9.15  0.35  7.57  NaN
7.92  8.49  7.43  7.06
9.59  9.33  3.92  0.31
09:10:02
23-Aug-1990
2.76  6.94  4.38  1.86
0.46  3.17  NaN   4.89
0.97  9.50  7.65  4.45
8.23  0.34  7.95  6.46

Считать файл:

filename = 'mymeas.dat';
measrows = 4;
meascols = 4;

% open the file
fid = fopen(filename);

% make sure the file is not empty
finfo = dir(filename);
fsize = finfo.bytes;

if fsize > 0 

    % read the file
    block = 1;
    while ~feof(fid)
        mystruct(block).mtime = fscanf(fid, '%s', 1);
        mystruct(block).mdate = fscanf(fid, '%s', 1);

        % fscanf fills the array in column order,
        % so transpose the results
        mystruct(block).meas  = ...
          fscanf(fid, '%f', [measrows, meascols])';

        block = block + 1;
    end

end

% close the file
fclose(fid);

Тестирование на EOF с fgetl и fgets

Если вы используете fgetl или fgets в цикле управления, feof не всегда лучший способ протестировать на конец файла. Как альтернатива, рассмотрите проверку ли значение что fgetl или fgets возвраты являются вектором символов.

Например, функциональный litcount описанный в Построчном чтении данных включает следующий while цикл и fgetl вызовы:

y = 0;
tline = fgetl(fid);
while ischar(tline)
   matches = strfind(tline, literal);
   num = length(matches);
   if num > 0
      y = y + num;
      fprintf(1,'%d:%s\n',num,tline);
   end
   tline = fgetl(fid);
end

Этот подход более устойчив, чем тестирование ~feof(fid) по двум причинам:

  • Если fgetl или fgets найдите данные, они возвращают вектор символов. В противном случае они возвращают номер (-1).

  • После каждой операции чтения, fgetl и fgets проверяйте следующий символ в файл для маркера конца файла. Поэтому эти функции иногда устанавливают индикатор конца файла, прежде чем они возвратят значение -1. Например, рассмотрите следующий текстовый файл с тремя строками. Каждый из первых двух концов линий с символом новой строки и третьей линии содержит только маркер конца файла:

    123
    456
    

    Три последовательных вызова fgetl приведите к следующим результатам:

    t1 = fgetl(fid);    % t1 = '123', feof(fid) = false
    t2 = fgetl(fid);    % t2 = '456', feof(fid) = true
    t3 = fgetl(fid);    % t3 = -1,    feof(fid) = true
    

    Это поведение не соответствует техническим требованиям ANSI для связанных функций языка C.

Вводные файлы с различными кодировками символов

Схемы кодирования поддерживают символы, требуемые для конкретных алфавитов, таких как те для японского или европейских языков. Общие схемы кодирования включают US-ASCII или UTF-8.

Если вы не задаете схему кодирования при открытии файла для чтения, fopen использует автоматическое обнаружение набора символов, чтобы определить кодирование. Если вы не задаете схему кодирования при открытии файла для записи, fopen значения по умолчанию к использованию UTF-8 для того, чтобы обеспечить функциональную совместимость между всеми платформами и локалями без потери данных или повреждения. Для получения дополнительной информации смотрите.

Чтобы определить значение по умолчанию, откройте файл и вызовите fopen снова с синтаксисом:

[filename, permission, machineformat, encoding] = fopen(fid);

Если вы задаете схему кодирования, когда вы открываете файл, следующие функции применяют ту схему: fscanffprintffgetlfgetsfread, и fwrite.

Для полного списка поддерживаемых схем кодирования и синтаксиса для определения кодирования, смотрите fopen страница с описанием.