Текстовий файл c си. Відкрити файл за допомогою функції Open. Оператори включення та вилучення

Теги: Текстові файли, fopen, fclose, feof, setbuf, setvbuf, fflush, fgetc, fprintf, fscanf, fgets, буферизований потік, небуферизований потік.

Робота з текстовими файлами

Робота з текстовим файлом схожа на роботу з консоллю: за допомогою функцій форматованого введення ми зберігаємо дані у файл, за допомогою функцій форматованого виводу зчитуємо дані з файлу. Є безліч нюансів, які ми розглянемо пізніше. Основні операції, які необхідно зробити, це

  • 1. Відкрити файл, щоб до нього можна було звертатися. Відповідно, відкривати можна для читання, запису, читання та запису, переписування або запису в кінець файлу і т.п. Коли ви відкриваєте файл, може також статися купа помилок - файлу може не існувати, це може бути файл не того типу, у вас може не мати рації на роботу з файлом і т.д. Все це потрібно враховувати.
  • 2. Безпосередньо робота з файлом - запис та читання. Тут також слід пам'ятати, що ми працюємо не з пам'яттю з довільним доступом, а з буферизованим потоком, що додає специфіку.
  • 3. Закрити файл. Оскільки файл є зовнішнім по відношенню до програми ресурсом, то якщо його не закрити, він продовжить висіти в пам'яті, можливо, навіть після закриття програми (наприклад, не можна буде видалити відкритий файлабо внести зміни тощо). Крім того, іноді необхідно не закривати, а "відкривати" файл для того, щоб, наприклад, змінити режим доступу.

Крім того, існує ряд завдань, коли нам не потрібно звертатися до вмісту файлу: перейменування, переміщення, копіювання і т.д. На жаль, у стандарті немає опису функцій для цих потреб. Вони, безумовно, є кожної з реалізацій компілятора. Зчитування вмісту каталогу (папки, директорії) – це також звернення до файлу, оскільки папка як така є файлом з метаинформацией.

Іноді необхідно виконувати деякі допоміжні операції: переміститися в потрібне місце, запам'ятати поточне положення, визначити довжину файлу і т.д.

Для роботи з файлом потрібний об'єкт FILE. Цей об'єкт зберігає ідентифікатор файлового потоку та інформацію, яка потрібна, щоб ним керувати, включаючи вказівник на буфер, індикатор позиції у файлі та індикатори стану.

Об'єкт FILE сам собою структурою, але його полям має бути доступу. Програма, що переноситься, повинна працювати з файлом як з абстрактним об'єктом, що дозволяє отримати доступ до файлового потоку.

Створення та виділення пам'яті під об'єкт типу FILE здійснюється за допомогою функції fopen або tmpfile (є й інші, але ми зупинимося лише на цих).

Функція fopen відкриває файл. Вона отримує два аргументи – рядок з адресою файлу та рядок із режимом доступу до файлу. Ім'я файлу може бути як абсолютним, і відносним. fopen повертає покажчик на об'єкт FILE, за допомогою якого можна здійснювати доступ до файлу.

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

Наприклад, відкриємо файл і запишемо в нього Hello World

#include #include #include void main() ( //З допомогою змінної file будемо здійснювати доступ до файлу FILE *file; //Відкриваємо текстовий файл із правами на запис file = fopen("C:/c/test.txt", "w+t") //Пишемо у файл fprintf(file, "Hello, World!"); //Закриваємо файл fclose(file); getch();

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

Функція fopen може відкривати файл у текстовому чи бінарному режимі. За промовчанням використовується текстовий. Режим доступу може бути наступним

Установки доступу до файлу.
Тип Опис
r Читання. Файл має існувати.
w Запис нового файлу. Якщо файл з таким ім'ям вже існує, його вміст буде втрачено.
a Запис у кінець файлу. Операції позиціонування (fseek, fsetpos, frewind) ігноруються. Файл створюється, а то й існував.
r+ Читання та оновлення. Можна як читати, і писати. Файл має існувати.
w+ Запис та оновлення. Створюється новий файл. Якщо файл з таким ім'ям вже існує, його вміст буде втрачено. Можна як писати, і читати.
a+ Запис у кінець та оновлення. Операції позиціонування працюють лише читання, для запису ігноруються. Якщо файл не існував, буде створено новий.

Якщо потрібно відкрити файл у бінарному режимі, то в кінець рядка додається буква b, наприклад “rb”, “wb”, “ab”, або для змішаного режиму “ab+”, “wb+”, “ab+”. Замість b можна додавати літеру t, тоді файл відкриватиметься в текстовому режимі. Це від реалізації. У новому стандарті си (2011) літера x означає, що функція fopen має завершитися помилково, якщо файл вже існує. Доповнимо нашу стару програму: заново відкриємо файл і вважаємо, що ми туди записали.

#include #include #include void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); fclose(file); file = fopen("C:/c/test.txt", "r"); fgets(buffer, 127, файл); printf("%s", buffer); fclose(file);

Замість функції fgets можна було використовувати fscanf, але слід пам'ятати, що вона може рахувати рядок тільки до першого пробілу.
fscanf(file, "%127s", buffer);

Також, замість того, щоб відкривати та закривати файл, можна скористатися функцією freopen, яка «перевідкриває» файл з новими правами доступу.

#include #include #include void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); freopen("C:/ c/test.txt", "r", файл); fgets(buffer, 127, файл); printf("%s", buffer); fclose(file);

Функції fprintf і fscanf відрізняються від printf і scanf тільки тим, що приймають як перший аргумент покажчик на FILE, в який вони виводитимуть або з якого читатимуть дані. Тут варто відразу додати, що функції printf і scanf можуть бути без проблем замінені функціями fprintf і fscanf. У ОС (ми розглядаємо найпоширеніші та адекватні операційні системи) існує три стандартні потоки: стандартний потік виведення stdout, стандартний потік введення stdin і стандартний потік виведення помилок stderr. Вони автоматично відкриваються під час запуску програми та пов'язані з консоллю. Приклад

#include #include #include void main() ( int a, b; fprintf(stdout, "Enter two numbers\n"); fscanf(stdin, "%d", &a); fscanf(stdin, "%d", &b); == 0) ( fprintf(stderr, "Error: divide by zero"); ) else ( fprintf(stdout, "%.3f", (float) a / (float) b); ) getch();

Помилка відкриття файлу

Якщо виклик функції fopen пройшов невдало, вона поверне NULL. Помилки під час роботи з файлами зустрічаються досить часто, тому щоразу, коли ми відкриваємо файл, необхідно перевіряти результат роботи

#include #include #include #define ERROR_OPEN_FILE -3 void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); if (file == NULL) ( printf("Error opening file"); getch(); exit(ERROR_OPEN_FILE); ) fprintf(file, "Hello, World!"); freopen("C:/c/test.txt", "r", file); = NULL) ( printf("Error opening file"); getch(); exit(ERROR_OPEN_FILE); ) fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch() ;)

Проблему викликає випадок, коли відкривається відразу кілька файлів: якщо один з них не можна відкрити, інші також повинні бути закриті

FILE *inputFile, *outputFile; unsigned m, n; unsigned i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if (inputFile == NULL) ( printf("Error opening file %s", INPUT_FILE); getch(); exit(3); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Error opening file %s", OUTPUT_FILE); getch(); if (inputFile != NULL) ( fclose(inputFile); ) exit(4); ) ...

У найпростіших випадках можна діяти лоб, як у попередньому шматку коду. У складніших випадках використовуються методи, що підміняють RAII із С++: обгортки, або особливості компілятора (cleanup в GCC) і т.п.

Буферизація даних

Як говорилося раніше, коли ми виводимо дані, вони спочатку поміщаються в буфер. Очищення буфера здійснюється

  • 1) Якщо він заповнений
  • 2) Якщо потік закривається
  • 3) Якщо ми явно вказуємо, що необхідно очистити буфер (тут також є винятки:)).
  • 4) Також очищається, якщо програма завершилася успішно. Разом з цим закриваються всі файли. У разі помилки виконання цього може статися.

Форсувати вивантаження буфера можна за допомогою функції fflush(File *). Розглянемо два приклади – з очищенням та без.

#include #include #include void main() ( FILE *file; char c; file = fopen("C:/c/test.txt", "w"); do ( c = getch(); fprintf(file, "%c", c) );fprintf(stdout, "%c", c); //fflush(file); ) while(c != "q"); fclose(file);

Розкоментуйте виклик fflush. Під час виконання відкрийте текстовий файл та подивіться на поведінку.

Буфер файлу можна призначити самостійно, задавши розмір. Робиться це за допомогою функції

Void setbuf (FILE * stream, char * buffer);

яка приймає вже відкритий FILE та покажчик на новий буфер. Розмір нового буфера повинен бути не меншим ніж BUFSIZ (наприклад, на поточній робочої станції BUFSIZ дорівнює 512 байт). Якщо передати як буфер NULL, то потік стане небуферизованим. Можна також скористатися функцією

Int setvbuf (FILE * stream, char * buffer, int mode, size_t size);

яка приймає буфер довільного розміру size. Режим mode може приймати такі значення

  • _IOFBF- Повна буферизація. Дані записуються у файл, коли він заповнюється. На зчитування буфер вважається заповненим, коли запитується операція введення і буфер порожній.
  • _IOLBF- Лінійна буферизація. Дані записуються у файл, коли він заповнюється, або коли зустрічається символ нового рядка. На зчитування буфер заповнюється до символу нового рядка, коли запитується операція введення і буфер порожній.
  • _IONBF- Без буферизації. У цьому випадку параметри size та buffer ігноруються.
У разі успішного виконання функція повертає 0.

Приклад: поставимо свій буфер і подивимося, як здійснюється читання з файлу. Нехай файл короткий (щось типу Hello, World!), і зчитуємо ми його посимвольно

#include #include #include void main() ( FILE *input = NULL; char c; char buffer = (0); input = fopen("D:/c/text.txt", "rt"); setbuf(input, buffer); while ( !feof(input)) ( c = fgetc(input); printf("%c\n", c); printf("%s\n", buffer); _getch(); ) fclose(input); )

Видно, що дані вже знаходяться у буфері. Зчитування посимвольно провадиться вже з буфера.

feof

Функція int feof (FILE * stream); повертає істину, якщо кінець файлу досягнуто. Функцію зручно використовувати, коли потрібно пройти весь файл від початку до кінця. Нехай є файл із текстовим вмістом text.txt. Вважаємо посимвольно файл та виведемо на екран.

#include #include #include void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Error opening file") ; _getch(); exit(0); ) while (!feof(input)) ( c = fgetc(input); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

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

#include #include #include void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Error opening file") ; _getch(); exit(0); ) while (!feof(input)) ( fscanf(input, "%c", &c); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

Цей приклад спрацює з помилкою (швидше за все) та виведе останній символ файлу двічі.

Рішення не використовувати feof. Наприклад, зберігати загальну кількість записів або використовувати той факт, що функції fscanf та ін зазвичай повертають число вірно лічених і зіставлених значень.

#include #include #include void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Error opening file") ; _getch(); exit(0); ) while (fscanf(input, "%c", &c) == 1) ( fprintf(stdout, "%c", c); ) fclose(input); _getch() ;)

Приклади

1. В одному файлі записані два числа – розмірності масиву. Заповнимо другий файл масивом випадкових чисел.

#include #include #include #include //Імена файлів та права доступу #define INPUT_FILE "D:/c/input.txt" #define OUTPUT_FILE "D:/c/output.txt" #define READ_ONLY "r" #define WRITE_ONLY "w" //Максимальне значення для розміру масиву #define MAX_DIMENSION 100 //Помилка при відкритті файлу #define ERROR_OPEN_FILE -3 void main() ( FILE *inputFile, *outputFile; unsigned m, n; unsigned i, j; inputFile == NULL) ( printf("Error opening file %s", INPUT_FILE); getch(); exit(ERROR_OPEN_FILE); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Error opening file %s", OUTPUT_FILE); getch(); //Якщо файл для читання вдалося відкрити, то його необхідно закрити if (inputFile != NULL) ( fclose(inputFile); ) exit(ERROR_OPEN_FILE); ) fscanf(inputFile, "%ud %ud", &m, &n), ​​if (m > MAX_DIMENSION) ( m = MAX_DIMENSION; ) if (n > MAX_DIMENSION) ( n = MAX_DIMENSION; ) srand(time(NULL)); for (i = 0; i< n; i++) { for (j = 0; j < m; j++) { fprintf(outputFile, "%8d ", rand()); } fprintf(outputFile, "\n"); } //Закрываем файлы fclose(inputFile); fclose(outputFile); }

2. Користувач копіює файл, спочатку вибирає режим роботи: файл може виводитися як у консоль, і копіюватися у новий файл.

#include #include #include #define ERROR_FILE_OPEN -3 void main() ( FILE *origin = NULL; FILE *output = NULL; char filename; int mode; printf("Enter filename: "); scanf("%1023s", filename); (filename, "r"); if (origin == NULL) ( printf("Error opening file %s", filename); getch(); exit(ERROR_FILE_OPEN); ) printf("enter mode: "); scanf( "%d", &mode); if (mode == 1) ( printf("Enter filename: "); scanf("%1023s", filename); output = fopen(filename, "w"); if (output = = NULL) ( printf("Error opening file %s", filename); getch(); fclose(origin); exit(ERROR_FILE_OPEN); ) ) else ( output = stdout; ) while (!feof(origin)) ( fprintf (output, "%c", fgetc(origin)); ) fclose(origin); fclose(output); getch();

3. Користувач вводить дані з консолі і вони записуються у файл доти, доки не буде натиснуто клавішу esc. Перевірте програму та подивіться. як вона поводиться у випадку, якщо ви вводите backspace: що виводиться у файл і що виводиться на консоль.

#include #include #include #define ERROR_FILE_OPEN -3 void main() ( FILE *output = NULL; char c; output = fopen("D:/c/test_output.txt", "w+t"); if (output == NULL) ( printf ("Error opening file"); _getch(); exit(ERROR_FILE_OPEN); ) for (;;) ( c = _getch(); c, stdout);) fclose(output);

4. У файлі записані цілі числа. Знайти максимальне їх. Скористаємося тим, що функція fscanf повертає кількість чітко прочитаних і зіставлених об'єктів. Щоразу має повертатися число 1.

#include #include #include #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Error opening file"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; hasRead = 1; while (hasRead == 1) ( hasRead = fscanf(input, "%d", &num); if (hasRead != 1) ( continue; ) if (num >

Інше рішення зчитувати числа, доки не дійдемо до кінця файла.

#include #include #include #include #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Error opening file"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; while (!feof(input)) ( fscanf(input, "%d", &num); ) ( maxn = num; ) ) printf("max number = %d", maxn); fclose(input); _getch(); )

5. У файлі записані слова: російське слово, табуляція, англійське слово, кілька рядів. Користувач запроваджує англійське слово, необхідно вивести російське.

Файл із перекладом виглядає приблизно так

Сонце sun
олівець pen
кулькова ручка pencil
двері door
вікно windows
стілець chair
крісло armchair

та збережений у кодуванні CP866 (OEM 866). При цьому важливо: остання пара слів також закінчується перекладом рядка.

Алгоритм наступний - зчитуємо рядок з файлу, знаходимо в рядку знак табуляції, підмінюємо знак табуляції нулем, копіюємо російське слово з буфера, копіюємо англійське слово з буфера, перевіряємо на рівність.

#include #include #include #include #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; char buffer; char enWord; char ruWord; char usrWord; unsigned index; int length; int wasFound; input = fopen("D:/c/input.txt ", "r"); if (input == NULL) ( printf("Error opening file"); _getch(); exit(ERROR_FILE_OPEN); ) printf("enter word: "); fgets(usrWord, 127, stdin );wasFound = 0;while (!feof(input)) ( fgets(buffer, 511, input); length = strlen(buffer); for (index = 0; index< length; index++) { if (buffer == "\t") { buffer = "\0"; break; } } strcpy(ruWord, buffer); strcpy(enWord, &buffer); if (!strcmp(enWord, usrWord)) { wasFound = 1; break; } } if (wasFound) { printf("%s", ruWord); } else { printf("Word not found"); } fclose(input); _getch(); }

6. Підрахувати кількість рядків у файлі. Зчитуватимемо файл посимвольно, рахуючи кількість символів "\n" доти, доки не зустрінемо символ EOF. EOF - це спецсимвол, який вказує на те, що введення закінчено і більше немає даних для читання. Функція повертає негативне значення у разі помилки.
ЗАУВАЖЕННЯ: EOF має тип int, тому потрібно використовувати int для зчитування символів. Крім того, значення EOF не визначено стандартом.

#define _CRT_SECURE_NO_WARNINGS #include #include #include int cntLines(const char *filename) ( int lines = 0; int any; //any типу int, тому що EOF має тип int! FILE *f = fopen(filename, "r"); if (f == NULL) ( return -1; ) do ( any = fgetc(f); //printf("%c", any);//debug if (any == "\n") ( lines++; ) ) while(any != EOF); ​​fclose(f); return lines; ) void main ()

Ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 [email protected] Stepan Sypachev students

Все ще незрозуміло? – пиши запитання на скриньку

Текстові файли

Розглянемо роботу з текстовим файлом Сі на прикладі. Створіть на диску текстовий файл з ім'ям TextFile.txt. Наберіть у цьому файлі такі рядки:

String_1 123 String_11, 456
String_2
String_3

Збережіть файл.

А це код програми на C, яка відкриває наш файл та зчитує з нього рядки:

/* *Author: @author Subbotin B.P..h> #include #define LEN 50 int main(void) ( puts("Text file operations"); char cArray; FILE *pTextFile = fopen("C:\\TextFile.txt", "r"); if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) while(fgets(cArray, LEN, pTextFile) != NULL) ( printf("%s", cArray); ) fclose(pTextFile); return EXIT_SUCCESS; )

Щоб відкрити текстовий файл C використовуємо функцію fopen:

FILE *pTextFile = fopen("C:\TextFile.txt", "r");

перший аргумент функції fopen вказує на файл, а другий каже, що файл відкритий для його читання.

Рядки зчитуємо за допомогою функції fgets:

fgets(cArray, LEN, pTextFile);

перший аргумент функції fgets вказує на масив символів, в якому будуть збережені отримані рядки, другий аргумент – це максимальна кількість символів для зчитування, третій – наш файл.

Після завершення роботи з файлом його треба закрити:

fclose(pTextFile);

Отримуємо:

Російські літери у рядках теж проходять.

До речі, цю програму я зробив у Eclipse. Як працювати з C/C++ в Eclipse можна переглянути .

Отже, ми відкрили та рахували дані з текстового файлу.

Тепер навчимося програмно створювати текстовий файл і записувати дані.

/* Author: @author Subbotin B.P..h> #include int main(void) ( FILE *pTextFile = fopen("C:\\TextFileW.txt", "w"); char *cString = "This is a string"; char cNewLine = "\n"; int nVal = 123 ; if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) fprintf(pTextFile, "%s%c", cString, cNewLine); fprintf(pTextFile, "%d", nVal); return EXIT_SUCCESS ;)

Створюємо текстовий файл для запису даних:

FILE *pTextFile = fopen("C:\\TextFileW.txt", "w");

якщо файл вже є, то він буде відкритий, і всі дані будуть видалені.

C-рядок cString і число nVal записуються програмою в текстовий файл. cNewLine – це просто перехід на новий рядок.

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

fprintf(pTextFile, %s%c, cString, cNewLine);

перший аргумент тут – наш файл, другий – форматний рядок, третій і більше – необхідна для цього формату кількість аргументів.

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

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

Каталог (папка, директорія) – іменована сукупність байтів на носії інформації, що містить назву підкаталогів та файлів, використовується у файловій системі для спрощення організації файлів.

Файловою системоюназивається функціональна частина операційної системи, Забезпечує виконання операцій над файлами. Прикладами файлових систем є FAT (FAT - File Allocation Table, таблиця розміщення файлів), NTFS, UDF (використовується на компакт-дисках).

Існують три основні версії FAT: FAT12, FAT16 та FAT32. Вони відрізняються розрядністю записів у дискової структурі, тобто. кількістю бітів, відведених для зберігання номера кластера. FAT12 застосовується переважно для дискет (до 4 кбайт), FAT16 – для дисків малого обсягу, FAT32 – для FLASH-накопичувачів великої ємності (до 32 Гбайт).

Розглянемо структуру файлової системина прикладі FAT32.

Файлова структура FAT32

Пристрої зовнішньої пам'яті у системі FAT32 мають не байтову, а блокову адресацію. Запис інформації у пристрій зовнішньої пам'яті здійснюється блоками чи секторами.

Сектор – мінімальна одиниця зберігання інформації, що адресується, на зовнішніх запам'ятовуючих пристроях. Як правило, розмір сектора фіксований та становить 512 байт. Для збільшення адресного простору пристроїв зовнішньої пам'яті сектора об'єднують у групи, які називаються кластерами.

Кластер – об'єднання кількох секторів, що може розглядатися як самостійна одиниця, що має певні властивості. Основною властивістю кластера є його розмір, який вимірюється в кількості секторів або кількості байт.

Файлова система FAT32 має таку структуру.

Нумерація кластерів, що використовуються для запису файлів, ведеться з 2. Як правило, кластер № 2 використовується кореневим каталогом, а починаючи з кластера № 3 зберігається масив даних. Сектори, що використовуються для зберігання інформації, представленої вище кореневого каталогу, кластери не об'єднуються.
Мінімальний розмір файлу на диску відповідає 1 кластеру.

Завантажувальний сектор починається такою інформацією:

  • EB 58 90 – безумовний перехід та сигнатура;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 – кількість байт у секторі (зазвичай 512);
  • 1 байт – кількість секторів у кластері;
  • 2 байти – кількість резервних секторів.

Крім того, завантажувальний сектор містить таку важливу інформацію:

  • 0x10 (1 байт) – кількість таблиць FAT (зазвичай 2);
  • 0x20 (4 байти) – кількість секторів на диску;
  • 0x2С (4 байти) – номер кластера кореневого каталогу;
  • 0x47 (11 байт) – мітка тому;
  • 0x1FE (2 байти) – сигнатура завантажувального сектора(55 AA).

Сектор інформації файлової системи містить:

  • 0x00 (4 байти) - сигнатура (52 52 61 41);
  • 0x1E4 (4 байти) - сигнатура (72 72 41 61);
  • 0x1E8 (4 байти) - кількість вільних кластерів, -1 якщо не відомо;
  • 0x1EС (4 байти) – номер останнього записаного кластера;
  • 0x1FE (2 байти) - сигнатура (55 AA).

Таблиця FAT містить інформацію про стан кожного кластера на диску. Молодші 2 байт таблиці FAT зберігають F8 FF FF 0F FF FF FF FF (що відповідає стану кластерів 0 та 1, фізично відсутніх). Далі стан кожного кластера містить номер кластера, в якому продовжується поточний файл або таку інформацію:

  • 00 00 00 00 – кластер вільний;
  • FF FF FF 0F – кінець поточного файлу.
  • 8 байт – ім'я файлу;
  • 3 байти - розширення файлу;

Кореневий каталог містить набір 32-бітних записів інформації про кожен файл, що містить таку інформацію:

У разі роботи з довгими іменами файлів (включаючи російські імена), кодування імені файлу проводиться в системі кодування UTF-16. При цьому для кодування кожного символу відводиться 2 байти. При цьому ім'я файлу записується у вигляді наступної структури:

  • 1 байт послідовності;
  • 10 байт містять найменші 5 символів імені файлу;
  • 1 байт атрибут;
  • 1 байт резервний;
  • 1 байт - контрольна сумаімені DOS;
  • 12 байт містять молодші 3 символи імені файлу;
  • 2 байти – номер першого кластера;
  • Інші символи довгого імені.

Робота з файлами у мові Сі

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

Коли потік відкривається для введення-виведення, він зв'язується зі стандартною структурою типу FILE , яка визначена stdio.h . Структура FILE містить потрібну інформацію про файл.

Відкриття файлу здійснюється за допомогою функції fopen(), яка повертає покажчик на структуру типу FILE, який можна використовувати для подальших операцій із файлом.

FILE *fopen(name, type);


name – ім'я файлу, що відкривається (включаючи шлях),
type — вказівник на рядок символів, що визначають спосіб доступу до файлу:
  • "r" - відкрити файл читання (файл повинен існувати);
  • "w" – відкрити порожній файл для запису; якщо файл існує, його вміст втрачається;
  • "a" - відкрити файл для запису на кінець (для додавання); файл створюється, якщо він не існує;
  • "r+" - відкрити файл для читання та запису (файл повинен існувати);
  • "w+" - відкрити порожній файл для читання та запису; якщо файл існує, його вміст втрачається;
  • "a+" - відкрити файл для читання та доповнення, якщо файл не існує, він створюється.

Значення, що повертається - покажчик на відкритий потік. Якщо виявлено помилку, то повертається значення NULL .

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

Значення, що повертається: значення 0, якщо потік успішно закритий; константа EOF, якщо сталася помилка.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#include
int main() (
FILE *fp;
char name = "my.txt";
if ((fp = fopen(name, "r")) == NULL )
{
printf( "Не вдалося відкрити файл");
getchar();
return 0;
}
// Відкрити файл вдалося
... // необхідні дії над даними
fclose(fp);
getchar();
return 0;
}

Читання символу з файлу:

char fgetc (потік);


Аргументом функції є покажчик на потік типу FILE. Функція повертає код символу. Якщо кінець файлу досягнуто або виникла помилка, повертається константа EOF .

Запис символу у файл:

fputc (символ, потік);

Аргументами функції є символ та покажчик на потік типу FILE. Функція повертає код символу.

Функції fscanf() і fprintf() аналогічні функцій scanf() і printf() , але працюють із файлами даних, і мають перший аргумент - покажчик на файл.

fscanf(потік, "ФорматВведення", аргументи);

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

Коли потік відкривається для введення-виводу, він зв'язується зі стандартною структурою типу FILE, визначеною stdio.h. Структура FILE містить потрібну інформацію про файл.

Відкриття файлу здійснюється за допомогою функції fopen(), яка повертається вказівник на структуру типу FILE, який можна використовувати для подальших операцій із файлом.

FILE *fopen(name, type);

name – ім'я файлу, що відкривається (включаючи шлях),
type - вказівник на рядок символів, що визначають спосіб доступу до файлу:

· "r" - відкрити файл для читання (файл має існувати);

· "w" - відкрити порожній файл для запису; якщо файл існує, його вміст втрачається;

· "a" - відкрити файл для запису в кінець (для додавання); файл створюється, якщо він не існує;

· "r+" - відкрити файл для читання та запису (файл повинен існувати);

· "w+" - відкрити порожній файл для читання та запису; якщо файл існує, його вміст втрачається;

· "a+" - відкрити файл для читання та доповнення, якщо файл не існує, то він створюється.

Значення, що повертається - покажчик на відкритий потік. Якщо виявлено помилку, то повертається значення NULL.

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

Значення, що повертається: значення 0, якщо потік успішно закритий; константа EOF, якщо сталася помилка.

#include
int main()

char name="my.txt";

if(fp = fopen(name, "r")!=NULL)

// Відкрити файл далося?
... // необхідні дії над даними

else printf("Не вдалося відкрити файл");

Читання символу з файлу:

char fgetc (потік);

Аргументом функції є покажчик потік типу FILE. Функція повертає код символу. Якщо кінець файлу досягнуто або виникла помилка, повертається константа EOF.
Запис символу у файл:

fputc (символ, потік);

Аргументами функції є символ та покажчик на потік типу FILE. Функція повертає код символу.

Функції fscanf() і fprintf() аналогічні функцій scanf() і printf(), але працюють із файлами даних, і мають перший аргумент - покажчик на файл.

fscanf(потік, "Формат Введення", аргументи);
fprintf (потік, "Формат Виводу", аргументи);

Функції fgets() і fputs() призначені для введення-виводу рядків, є аналогами функцій gets() і puts() до роботи з файлами.

fgets(Покажчик на Рядок, Кількість Символів, потік);

Символи читаються з потоку доти, доки не буде прочитано символ нового рядка "\n", який включається до рядка, або доки не настане кінець потоку EOF або не буде прочитано максимальне символів. Результат міститься в покажчик на рядок і закінчується нуль-символом "\0". Функція повертає адресу рядка.

fputs(Покажчик на Рядок, потік);

Копіює рядок у потік із поточної позиції. Завершальний нуль-символ не копіюється.
Приклад Ввести число та зберегти його у файлі s1.txt. Вважати число з файлу s1.txt, збільшити його на 3 і зберегти у файлі s2.txt.

Файли дозволяють користувачеві зчитувати великі обсяги даних безпосередньо з диска без введення їх з клавіатури. Існують два основних типи файлів: текстові та двійкові.

Текстовиминазиваються файли, які з будь-яких символів. Вони організовуються по рядках, кожен із яких закінчується символом « кінця рядка». Кінець файлу позначається символом « кінця файлу». При записі інформації в текстовий файл, переглянути який можна за допомогою будь-якого текстового редактора, всі дані перетворюються на символьний тип і зберігаються у символьному вигляді.

В двійковихУ файлах інформація зчитується і записується у вигляді блоків певного розміру, в яких можуть зберігатися дані будь-якого виду та структури.

Для роботи з файлами використовуються спеціальні типи даних, які називаються потоками.Потік ifstreamслужить до роботи з файлами як читання, а ofstreamв режимі зйомки. Для роботи з файлами в режимі запису, так і читання служить потік fstream.

У програмах на C++ під час роботи з текстовими файлами необхідно підключати бібліотеки iostreamі fstream.

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

  1. описати змінну типу ofstream.
  2. open.
  3. вивести інформацію у файл.
  4. обов'язково закрити файл.

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

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

Запис інформації у текстовий файл

Як було сказано раніше, щоб почати працювати з текстовим файлом, необхідно описати змінну типу ofstream. Наприклад, так:

ofstream F;

Буде створено змінну Fдля запису інформації у файл. На наступному етапі файл потрібно відкрити для запису. У загальному випадку оператор відкриття потоку матиме вигляд:

F.open("file", mode);

Тут F- змінна, описана як ofstream, file - повне ім'яфайлу на диску, mode- режим роботи з файлом, що відкривається. Зверніть увагу, що при вказівці повного імені файлу потрібно ставити подвійний слєш. Для звернення, наприклад, до файлу accounts.txt,що знаходиться в папці sites на диску D, у програмі необхідно вказати: D:\\sites\\ accounts.txt.

Файл може бути відкритий в одному з таких режимів:

  • ios::in- Відкрити файл в режимі читання даних; режим є стандартним режимом для потоків ifstream;
  • ios::out- відкрити файл у режимі запису даних (при цьому інформація про наявний файл знищується); режим є стандартним режимом для потоків ofstream;
  • ios::app- Відкрити файл в режимі запису даних в кінець файлу;
  • ios::ate- пересунутись на кінець вже відкритого файла;
  • ios::trunc- очистити файл, це відбувається в режимі ios::out;
  • ios::nocreate- не виконувати операцію відкриття файлу, якщо він не існує;
  • ios::noreplace- не відкривати існуючий файл.

Параметр mode може бути відсутнім, у цьому випадку файл відкривається в режимі за промовчанням для цього потоку.

Після вдалого відкриття файлу (у будь-якому режимі) у змінній Fбуде зберігатися true, в іншому випадку false. Це дозволить перевірити правильність операції відкриття файлу.

Відкрити файл (як приклад візьмемо файл D:\\sites\\ accounts.txt) в режимі запису можна одним із наступних способів:

Після відкриття файлу в режимі запису буде створено порожній файл, який можна буде записувати інформацію.

Якщо ви хочете відкрити існуючий файл у режимі дозапису, то як режим слід використовувати значення ios::app.

Після відкриття файлу в режимі запису, в нього можна писати так само, як і на екран, тільки замість стандартного пристроювисновку coutпотрібно вказати ім'я відкритого файлу.

Наприклад, для запису в потік Fзмінної a, оператор виводу матиме вигляд:

F<

Для послідовного виведення в потік Gзмінних b, c, dоператор виведення стане таким:

G<

Закриття потоку здійснюється за допомогою оператора:

F.close();

Як приклад розглянемо таку задачу.

Завдання 1

Створити текстовий файл D:\\ sites\\accounts .txtі записати в нього nдійсних чисел.

Рішення

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "stdafx.h"
#include
#include
#include
using namespace std;
int main()
{

int i, n;
double a;
//описує потік для запису даних у файл
ofstream f;
//відкриваємо файл у режимі запису,
//режим ios::out встановлюється за умовчанням
f.open («D: \\ sites\\ accounts.txt», ios:: out);
//вводимо кількість речових чисел
cout<< «n=» ; cin >> n;
//цикл для введення дійсних чисел
//і записи їх у файл
for (i= 0; i< n; i++ )
{
cout<< «a=» ;
//введення числа
cin >> a;
f<< a<< «\t «;
}
//закриття потоку
f.close ();
system («pause»);
return 0;
}

Читання інформації з текстового файлу

Щоб прочитати інформацію з текстового файлу, необхідно описати змінну типу ifstream. Після цього потрібно відкрити файл для читання за допомогою оператора open. Якщо змінну назвати F, то перші два оператори будуть такими:

Після відкриття файлу в режимі читання з нього можна зчитувати інформацію так само, як і з клавіатури, тільки замість cinНеобхідно вказати ім'я потоку, з якого відбуватиметься читання даних.

Наприклад, для читання даних із потоку Fу змінну a, оператор введення виглядатиме так:

F>>a;

Два числа в текстовому редакторі вважаються розділеними, якщо між ними є хоча б один із символів: пробіл, табуляція, символ кінця рядка. Добре, коли програмісту наперед відомо, скільки і які значення зберігаються в текстовому файлі. Однак часто відомий лише тип значень, що зберігаються у файлі, при цьому їх кількість може бути різною. Для вирішення цієї проблеми необхідно зчитувати значення з файлу по черзі, а перед кожним зчитуванням перевіряти, чи кінець файлу досягнуто. А допоможе зробити цю функцію F.eof(). Тут F- ім'я потоку функція повертає логічне значення: trueабо false, залежно від того, чи кінець файлу досягнуто.

Отже, цикл для читання вмісту всього файлу можна записати так:

Для найкращого засвоєння матеріалу розглянемо завдання.

Завдання 2

У текстовому файлі D:\game\accounts.txt зберігаються речові числа, вивести їх на екран і обчислити їх кількість.

Рішення

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#include "stdafx.h"
#include
#include
#include
#include
using namespace std;
int main()
{
setlocale (LC_ALL, "RUS");
int n = 0;
float a;
fstream F;
//відкриваємо файл у режимі читання
F.open («D: \\ sites\\ accounts.txt») ;
//якщо відкриття файлу пройшло коректно, то
if (F)
{
//цикл для читання значень із файлу; виконання циклу перерветься,
//Коли досягнемо кінця файлу, у разі F.eof() поверне істину.
while (! F.eof () )
{
//читання чергового значення з потоку F змінну a
F>> a;
//виведення значення змінної a на екран
cout<< a<< «\t «;
//збільшення кількості лічених чисел
n++;
}
//закриття потоку
F.close ();
//Вовод на екран кількості лічених чисел
cout<< «n=» << n<< endl;
}
//якщо відкриття файлу пройшло некоректно, висновок
//повідомлення про відсутність такого файлу
else cout<< " Файл не існує"<< endl;
system («pause»);
return 0;
}

На цьому відносно об'ємний урок із текстових файлів закінчено. У наступній статті будуть розглянуті методи маніпуляції, за допомогою яких C++ обробляються .

2021 wisemotors.ru. Як це працює. Залізо. Майнінг. Криптовалюта.