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

Обзор

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

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

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

Примечание

Низкоуровневые функции ввода-вывода файлов основаны на функциях в ANSI® Стандартная библиотека C. Однако MATLAB® включает векторизованные версии функций для чтения и записи данных в массив с минимальными циклами управления.

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

Чтобы импортировать текстовые файлы, которые importdata и textscan не может читать, рассмотрите использование fscanf. The 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. The 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 functions, перемещает индикатор положения файла.

Тестирование на EOF с периодичностью

Когда вы используете textscan, fscanf, или 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);

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

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