Компания ALT Linux
Опубликован: 12.03.2015 | Доступ: свободный | Студентов: 576 / 64 | Длительность: 20:55:00
Лекция 3:

Программирование

3.4.2 Обработка двоичных файлов

Двоичный файл, как и текстовый открывается с помощью функции fopen. Разница в том, что в параметре mode вместо буквы t должна использоваться буква b (от слова binary — двоичный): rb+, wb+ и т.д.

Чтение из двоичного файла осуществляется с помощью обращения к функции

[A, n] = fread(f, n, type);, где f — идентификатор файла, n — количество считываемых из файла элементов, type — тип считываемых из файла элементов.

Возможные значения параметра type приведены в табл. 3.5.

Таблица 3.5. Возможные значения параметра type
Параметр type Размер(байт) Описание
uchar 1 Целое число без знака (0 \div 255)
schar 1 Целое со знаком (-128 \div 127)
int16 2 Целое со знаком (-32768 \div 32767)
int32 4 Целое со знаком (-2147483648 \div 2147483647)
int64 8 Целое со знаком -(2^63- 1) \div (2^63- 1)
uint16 2 Целое без знака (0 \div 65535)
uint32 4 Целое без знака (0 \div 4294967295)
uint64 8 Целое без знака (0 \div 2^64-1)
float32 4 Вещественное число (3.4E - 38 \div 3.4E + 38)
float64 8 Вещественное число (1.7E - 308 \div 1.7E + 308)

Функция fread считывает из предварительно открытого файла с идентификатором f n элементов типа type и записывает их в массив (матрицу) A, количество реально читанных элементов возвращается в переменной n. Если при обращении к функции fread отсутствует параметр type, то подразумевается что из двоичного файла будут считываться значения типа uchar (однобайтовое целое без знака). Если пропущен и параметр n, то в массив A будут считываться все значения до конца файла. Параметр n может быть представлен в виде [mk], в этом случае данные считываются в матрицу размером m \times k.

Файл — последовательная структура данных. После открытия файла доступен первый элемент, хранящийся в файле. После чтения очередной порции данных указатель файла смещается на следующую порцию данных.

Текущая позиция указателя файла (смещения от начала файла в байтах) возвращается функцией ftell(f), здесь f — идентификатор уже открытого с помощью fopen файла.

Для перемещения указателя в начало файла служит функция frewind(f );

Функция fseek(f, n, origin); обеспечивает все остальные перемещения указателя файла. Функция перемещает текущую позицию в файле с идентификатором f на n байт относительно позиции origin.

Параметр origin может принимать одно из следующих значений:

  • строка 'bof' или число -1 определяет смещение относительно начала файла, в этом случае значение n может быть только положительным;
  • строка 'eof' или число 1 определяет смещение относительно конца файла на n байтов назад, в этом случае значение n также должно быть положительным;
  • строка 'cof' или число 0 определяет смещение относительно текущей позиции на n байтов вперёд (n > 0) или назад (n < 0).

Запись в двоичный файл осуществляется с помощью функции n = fwrite(f, A, type), где f — идентификатор файла, A — массив (матрица) значений, type — тип записываемых в файл элементов.

Функция fwrite записывает в заранее открытый файл с идентификатором f массив A, и возвращает количество реально записанных в файл значений n.

Рассмотрим несколько примеров работы с двоичными файлами.

Пример 3.14. Создать двоичный файл abc.dat, куда записать целое число N, а затем N вещественных чисел.

Решить эту задачу можно двумя способами:

  1. Записать в файл целое число N, а затем в цикле N вещественных чисел.
  2. Записать в файл целое число N, а затем одним оператором fwrite записать в файл массив из N вещественных чисел.

Решение задачи с комментариями обоими способами представлено в листинге 3.16.

	
% Первый способ _________________________
N=input(’N=’); % Ввод значения переменной N.
f=fopen(’abc.dat’, ’wb’); % Открытие двоичного файла abc.dat
						% в режиме 
	записи2Если файл abc.dat не существовал, он создастся, если существовал — все его содержимое будет утеряно. (Прим. редактора).
fwrite(f, N, ’int16’); % Запись числа N в двоичный файл abc.dat.
for i =1:N % Цикл для ввода N вещественных чисел и записи их в файл
	x=input(’X=’); % Ввод очередного вещественного числа x.
	fwrite(f, x, ’float32’); % Запись очередного числа x в файл.
end;
fclose(f); % Закрытие файла.
% Второй способ _________________________
N=input(’N=’); % Ввод значения переменной N.
f=fopen(’abc.dat’, ’wb’); % Открытие двоичного файла для записи.
fwrite(f, N, ’int16’); % Запись числа N в двоичный файл abc.dat.
for i =1:N % Цикл для ввода массива из N вещественных чисел.
	x ( i )=input(strcat(’x(’, int2str(i), ’)=’ ) ); % Ввод очередного
													% вещественного числа в массив x.
end;
fwrite(f, x, ’float32’); % Запись массива x в двоичный файл abc.dat.
fclose(f); % Закрытие файла.
Листинг 3.16. Запись числа в двоичный файл (пример 3.14).

В результате будет сформирован двоичный файл размером N*4+2 байт. Запустим любую из этих программ на выполнение в командной строке, введём N = 20 и сформируем файл abc.dat размером 82 байта.

Пример 3.15. Считать данные из файла abc.dat, сформированного в задаче из примера 3.14 в массив вещественных чисел.

Программа решения этой задачи представлена в листинге 3.17.

	
f=fopen(’abc.dat’, ’rb’);% Открытие файла abc.dat в режиме чтения.
N=fread(f, 1, ’int16’); % Чтение числа N из двоичного файла abc.dat.
x=fread(f, N, ’float32’); % Чтение массива из N вещественных чисел
						% из двоичного файла abc.dat
fclose(f); % Закрытие файла.
Листинг 3.17. Чтение данных из файла в массив (пример 3.15).

Пример 3.16. Считать данные из файла abc.dat, сформированного в задаче из примера 3.14 в матрицу вещественных чисел.

Зная, что в файле abc.dat хранится 20 чисел, в качестве примера запишем их в матрицу размером 4 \times 5. Программа решения этой задачи представлена в листинге 3.18. В результате работы этой программы будет сформирована матрица вещественных чисел G(4, 5).

	
f=fopen(’abc.dat’, ’rb’); % Открытие файла abc.dat в режиме чтения.
N=fread(f, 1, ’int16’); % Чтение числа N из двоичного файла abc.dat.
G=fread(f, [4 5], ’float32’); % Чтение матрицы вещественных чисел
							% G(4, 5) из двоичного файла abc.dat.
fclose(f); % Закрытие файла.
>>> G
G =
1.20000 9.00000 7.40000 8.90000 5.40000
3.40000 0.10000 6.50000 0.90000 4.30000
5.60000 9.20000 5.60000 8.70000 3.20000
7.80000 8.30000 7.80000 6.50000 2.10000
Листинг 3.18. Чтение данных из файла в матрицу (пример 3.15).

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

	
N=input(’N=’); % Ввод значения переменной N.
f=fopen(’abc2.dat’, ’wb’);% Открытие файла abc2.dat в режиме записи.
for i =1:N % Цикл для ввода N вещественных чисел и записи их в файл.
	x=input(’X=’);% Ввод очередного вещественного числа x.
	fwrite(f, x, ’float32’); % Запись числа x в файл abc2.dat.
end;
fclose(f); 
Листинг 3.19. Создание двоичного файла с вещественными числами

Отличие этой программы от представленных в листингах 3.17 и 3.18 состоит в том, что оличество записанных в файл abc2.dat вещественных чисел в нём не хранится. Поэтому чтение данных из такого файла осуществляется несколько иначе. Известно, что функция ftell(f) возвращает текущее положение указателя файла. Если с помощью функции fseek(f, 0, 1) передвинуть указатель в конец файла, а затем обратиться к функции ftell(f), можно вычислить количество байт в файле. Разделив полученное число на 4 (размера вещественного числа типа float32), получим количество элементов в файле, после чего считаем нужное количество элементов в массив с помощью функции fread.

Программа, реализующая описанные выше действия, представлена в листинге 3.20.

	
f=fopen(’abc2.dat’, ’rb’);% Открытие файла abc2.dat в режиме чтения.
fseek(f, 0, 1); % Перевод указателя в конец файла.
N= ftell(f) / 4; % Вычисляем количество байт в файле и делим на размер
				% одного элемента, для float32 это число 4
frewind(f); % Переводим указатель на начало файла
x=fread(f, N, ’float32’); % Чтение из файла abc2.dat в массив x N чисел.
fclose(f);% Закрытие файла.
Листинг 3.20. Чтение из двоичного файла неизвестного размера

Аналогичным образом можно будет считать данные любого типа из двоичного файла. Отличие будет состоять только в том, что в операторе N=ftell(f)/4; необходимо заменить число 4 на действительный размер элементов, хранящихся в файле и при обращении к функции fread указать в качестве третьего параметра реальный тип считываемых данных. Функция fread не считает больше элементов, чем находится в файле, независимо от того, что указано во втором параметре. Поэтому, если в листинге 3.20 оператор вычисления N записать следующим образом N=ftell(f), то программа будет корректно считывать данные в массив любого типа. Будет происходить следующее: оператор x=fread(f,N,type) попытается считать N элементов из двоичного файла, но не считает значений больше, чем их там есть, и остановится в конце файла.

Алексей Игнатьев
Алексей Игнатьев

Возможна ли разработка приложения на Octave с GUI?

Евгений Ветчанин
Евгений Ветчанин

Добрый день. Я самостоятельно изучил курс "Введение в Octave" и хочу получить сертификат. Что нужно сднлать для этого? Нужно ли записаться на персональное обучение с тьютором или достаточно перевести деньги?