Обробка двійкових файлів в c

При запису інформації в двійковий файл символи і числа записуються у вигляді послідовності байт.

Для того щоб записати дані в двійковий файл, необхідно:

  1. описати файлову змінну типу FAIL * за допомогою оператора FILE * filename. тут filename - ім'я змінної, де буде зберігатися покажчик на файл.
  2. відкрити файл за допомогою функції fopen
  3. записати інформацію в файл за допомогою функції fwrite
  4. закрити файл за допомогою функції fclose

Для того щоб вважати дані з виконуваного файлу, необхідно:

  1. описати змінну типу FILE *
  2. відкрити файл за допомогою функції fopen
  3. вважати необхідну інформацію з файлу за допомогою функції fread. при цьому стежити за тим чи досягнуто кінець файлу.
  4. закрити файл за допомогою функції fclose

Розглянемо основні функції, необхідні для роботи з двійковими файлами.

Для відкриття файлу призначена функція fopen.

FILE * fopen (const * filename, const char * mode)

Тут filename - рядок, в якій зберігається повне ім'я файлу, що відкривається, mode - рядок, що визначає режим роботи з файлом; можливі наступні значення:

  • «Rb» - відкриваємо двійковий файл в режимі читання;
  • «Wb» - створюємо двійковий файл для запису; якщо він існує, то його вміст очищається;
  • «Ab» - створюємо або відкриваємо двійковий файл для дозаписи в кінець файлу;
  • «Rb +» - відкриваємо існуючий двійковий файл в режимі читання і запису;
  • «Wb +» - відкриваємо двійковий файл в режимі читання і запису, існуючий файл очищається;
  • «Ab +» - двійковий файл відкривається або створюється для виправлення існуючий інформації і додавання нової в кінець файлу.

Функція повертає в файлової змінної f значення NULL в разі невдалого відкриття файлу. Після відкриття файлу доступний 0-й його байт, покажчик файлу дорівнює 0, значення якого в міру читання або запису зміщується на лічений (записане) кількість байт. Поточні значення покажчика файлу - номер байта, починаючи з якого буде відбуватися операція читання або запису.

Для закриття файлу призначена функція fclose:

int fclose (FILE * filename);

Вона повертає 0 при успішному закриття файлу і EOF в іншому випадку.

Функція remove призначена для видалення файлів:

int remove (const char * filename);

Ця функція видаляє з диска файл з ім'ям filenema. Видаляється файл повинен бути закритий. Функція повертає нульове значення, якщо файл не вдалося видалити.

Для перейменування файлів призначена функція rename:

int rename (const char * oldfilename, const char * newfilename);

Перший параметр - старе ім'я файлу, другий - нове. Повертає 0 при вдалому завершенні програми.

Читання з виконуваного файлу здійснюється за допомогою функції fread:

fread (void * ptr, size, n, FILE * filename);

Функція fread зчитує з файлу filename в масив ptr n елементів розміру size. Функція повертає кількість лічених елементів. Після читання з файлу його покажчик зміщується на n * size байт.

Запис в двійковий файл здійснюється за допомогою функції fwrite:

fwrite (const void * ptr, size, n, FILE * filename);

Функція fwrite записує в файл filename з масиву ptr n елементів розміру size. Функція повертає кількість записаних елементів. Після запису інформації в файл покажчик зміщується на n * size байт.

Для контролю досягнення кінця файлу є функція feof:

Вона повертає нульове значення якщо досягнуто кінець файлу.

Для більш точного засвоєння матеріалу пропоную розглянути пару стандартних завдань.

Створити двійковий файл D: \\ game \\ noobs.dat і записати в нього ціле число n і n дійсних чисел.

#include "stdafx.h"
#include
using namespace std;
int main # 40; # 41;
# 123;
setlocale # 40; LC_ALL, "RUS" # 41; ;
int n, i;
double a;
FILE * f; // описуємо файлову змінну
// створюємо двійковий файл в режимі запису
f = fopen # 40; "D: \\ game \\ noobs.dat". "Wb" # 41; ;
// введення числа n
cout <<"n=" ; cin>> N;
fwrite # 40; n, sizeof # 40; int # 41 ;. 1. f # 41; ;
// цикл для введення n дійсних чисел
for # 40; i = 0; i # 123;
// введення чергового дійсного числа
cout <<"a=" ;
cin >> a;
// запис вешественного числа в двійковий файл
fwrite # 40; a, sizeof # 40; double # 41 ;. 1. f # 41; ;
# 125;
// закриваємо файл
fclose # 40; f # 41; ;
system # 40; "Pause" # 41; ;
return 0;
# 125;

Вивести на екран вмісту створеного в минулому завданні виконуваного файлу D: \\ game \\ noobs.dat

#include "stdafx.h"
#include
using namespace std;
int main # 40; # 41;
# 123;
setlocale # 40; LC_ALL, "RUS" # 41; ;
int n, i;
double * a;
FILE * f; // описуємо файлову змінну
// відкриваємо існуючий двійковий файл в режимі читання
f = fopen # 40; "D: \\ game \\ noobs.dat". "Rb" # 41; ;
// зчитуємо з файлу одне ціле число в змінну n
fread # 40; n, sizeof # 40; int # 41 ;. 1. f # 41; ;
// вивід n на екран
cout <<"n=" < // виділення пам'яті для масиву з n чисел
a = new double # 91; n # 93; ;
// читання n дійсних чисел з файлу в масив a
fread # 40; a, sizeof # 40; double # 41 ;. n, f # 41; ;
// вивід масиву на екран
for # 40; i = 0; i cout < cout < // закриваємо файл
fclose # 40; f # 41; ;
system # 40; "Pause" # 41; ;
return 0;
# 125;

Двійковий файл - послідовна структура даних, після відкриття файлу доступний перший байт, що зберігається в ньому. Можна послідовно записувати або зчитувати дані з файлу. Припустимо, необхідно вважати п'ятнадцяте число, а потім перше. За допомогою послідовного доступу це можна зробити наступним способом:

int n, i;
double a;
FILE * f;
f = fopen # 40; "D: \\ game \\ noobs.dat". "Rb" # 41; ;
for # 40; i = 0; i <15 ; i ++ )
fread # 40; a, sizeof # 40; double # 41 ;. 1. f # 41; ;
fclose # 40; f # 41; ;
f = fopen # 40; "D: \\ game \\ noobs.dat". "Rb" # 41; ;
fread # 40; a, sizeof # 40; double # 41 ;. 1. f # 41; ;
fclose # 40; f # 41; ;

Як видно, таке читання чисел з файлу, а потім повторне відкриття файлу - не найзручніший спосіб. Набагато зручніше буде використовувати функцію fseek переміщення покажчика файлу до заданого байту.

int fseek (FILE * filename, long int offset, int origin);

Функція встановлює покажчик поточний позиції файлу F відповідно до значення початку відліку origin і зміщення offset. Параметр offset дорівнює кількості байтів, на які буде зміщений покажчик файлу щодо початку відліку, заданого параметром origin. Як значення для параметра origin має бути взято одне з наступних значень відліку зміщення offset. визначених у заголовку stdio.h:

  • SEEK_SET - з початку файлу;
  • SEEK_CUR - з поточної позиції;
  • SEEK_END - з кінця файлу.

Функція повертає нульове значення при успішному виконання операції, нульове - при виникненні збою при виконанні зміщення

Функція fseek фактично реалізує прямий доступ до будь-якого значення в файлі. Необхідно тільки знати місце розташування (номер байта) значення у файлі. Розглянемо використання прямого доступу в довічних файлах на прикладі рішення наступної задачі.

У створеному раннє довічним файлі D: \\ game \\ noobs.dat. поміняти місцями найбільше і найменше з дійсних чисел.

Алгоритм розв'язання задачі складається з наступних етапів:

  1. читання речових з файлу в масив a.
  2. пошук в масиві а максимального (max) і мінімального (min) значення і їх номерів (imax. imin).
  3. переміщення покажчика файлу до максимального значення і запис min.
  4. переміщення покажчика файлу до мінімального значення і запис max.

#include "stdafx.h"
#include
using namespace std;
int main # 40; # 41;
# 123;
setlocale # 40; LC_ALL, "RUS" # 41; ;
int n, i, imax, imin;
double * a, max, min;
FILE * f;
// відкриття файлу в режимі читання і запису
f = fopen # 40; "D: \\ game \\ noobs.dat". "Rb +" # 41; ;
// зчитуємо з файлу в змінну n кількість
// дійсних чисел у файлі
fread # 40; n, sizeof # 40; int # 41 ;. 1. f # 41; ;
cout <<"n=" < // виділяємо пам'ять для зберігання дійсних чисел,
// які будуть зберігатися в масиві a
a = new double # 91; n # 93; ;
// зчитуємо з файлу в масив а речові числа
fread # 40; a, sizeof # 40; double # 41 ;. n, f # 41; ;
// пошук максимального та мінімального елементів
// в масиві а й їх індексів
for # 40; imax = imin = 0. max = min = a # 91; 0 # 93 ;. i = 1; i # 123;
if # 40; a # 91; i # 93;> max # 41;
# 123;
max = a # 91; i # 93; ;
imax = i;
# 125;
if # 40; a # 91; i # 93; # 123;
min = a # 91; i # 93; ;
imin = i;
# 125;
# 125;
// переміщення покажчика до максимального елементу
fseek # 40; f, sizeof # 40; int # 41; + Imax * sizeof # 40; double # 41 ;. SEEK_SET # 41; ;
// запис min замість максимального елемента файлу
fwrite # 40; min, sizeof # 40; double # 41 ;. 1. f # 41; ;
// переміщення покажчика до мінімального елементу
fseek # 40; f, sizeof # 40; int # 41; + Imin * sizeof # 40; double # 41 ;. SEEK_SET # 41; ;
// запис max замість мінімального елемента файлу
fwrite # 40; max, sizeof # 40; double # 41 ;. 1. f # 41; ;
// закриття файлу
fclose # 40; f # 41; ;
// звільнення пам'яті
delete # 91; # 93; a;
system # 40; "Pause" # 41; ;
return 0;
# 125;

Отже, ми розглянули основні принципи роботи з файлами в C ++. У наступних уроках вони вам ще зустрінуться, тому запам'ятайте їх якнайкраще.