Контакти

Робота з даними з файлу c. Робота з текстовими файлами. Читання з виконуваного файлу і запис в нього

Робота файлового введення / виводу в C ++ майже аналогічна роботі звичайних (але з невеликими нюансами).

Класи файлового введення / виводу

є три основні класи файлового введення / виводу в C ++:

ofstream(Є дочірнім класу);

fstream(Є дочірнім класу iostream).

За допомогою цих класів можна виконувати односпрямований файловий ввід, односпрямований файловий висновок і двонаправлений файловий ввід / вивід. Для їх використання потрібно всього лише підключити fstream.

На відміну від потоків cout, cin, cerr і clog, які відразу ж можна використовувати, файлові потоки повинні бути явно встановлені програмістом. Тобто, щоб відкрити файл для читання і / або запису, потрібно створити об'єкт відповідного класу файлового введення / виводу, вказавши ім'я файлу в якості параметра. Потім, за допомогою операторів вставки (<<) или извлечения (>>), Можна записувати дані в файл або читати вміст файлу. Після цього фінал - потрібно закрити файл: явно викликати метод close ()або просто дозволити файлової змінної введення / виведення вийти з області видимості (файлового класу введення / виведення закриє цей файл автоматично замість нас).

файловий висновок

Для запису в файл використовується клас ofstream. наприклад:

#include #include #include // для використання exit () int main () (using namespace std; // ofstream використовується для запису даних в файл // Створюємо файл SomeText.txt ofstream outf ( "SomeText.txt"); // Якщо ми не можемо відкрити цей файл для запису даних в нього if (! outf) (// Те виводимо повідомлення про помилку і виконуємо exit () cerr<< "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } // Записываем в файл следующие две строчки outf << "See line #1!" << endl; outf << "See line #2!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#include

#include

#include // для використання exit ()

int main ()

using namespace std;

// ofstream використовується для запису даних в файл

// Створюємо файл SomeText.txt

ofstream outf ( "SomeText.txt");

// Якщо ми не можемо відкрити цей файл для запису даних в нього

if (! outf)

// Те виводимо повідомлення про помилку і виконуємо exit ()

cerr<< << endl ;

exit (1);

// Записуємо в файл наступні два рядки

outf<< "See line #1!" << endl ;

outf<< "See line #2!" << endl ;

return 0;

// Коли outf вийде з зони видимості, то деструктор класу ofstream автоматично закриє наш файл

Якщо ви загляньте в каталог вашого проекту ( ПКМ по вкладці з назвою вашего.cpp файлу в Visual Studio > «Відкрити що містить папку»), То побачите файл з ім'ям SomeText.txt, в якому знаходяться такі рядки:

See line # 1!
See line # 2!

Зверніть увагу, ми також можемо використовувати метод put ()для запису одного символу в файл.

файловий ввід

#include #include #include #include // для використання exit () int main () (using namespace std; // ifstream використовується для читання вмісту файлу // Спробуємо прочитати вміст файлу SomeText.txt ifstream inf ( "SomeText.txt"); // Якщо ми не можемо відкрити цей файл для читання його вмісту if (! inf) (cerr<< "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть данные, которые мы можем прочитать while (inf) { // То перемещаем эти данные в строку, которую затем выводим на экран string strInput; inf >> StrInput; cout<< strInput << endl; } return 0; }

#include

#include

#include

#include // для використання exit ()

int main ()

using namespace std;

// ifstream використовується для читання вмісту файлу

// Якщо ми не можемо відкрити цей файл для читання його вмісту

if (! inf)

// Те виводимо наступне повідомлення про помилку і виконуємо exit ()

cerr<< << endl ;

exit (1);

// Поки є дані, які ми можемо прочитати

while (inf)

// Те перемещаем ці дані в рядок, яку потім виводимо на екран

string strInput;

inf >> strInput;

cout<< strInput << endl ;

return 0;

// Коли inf вийде з зони видимості, то деструктор класу ifstream автоматично закриє наш файл

See
line
#1!
See
line
#2!

Хм, це не зовсім те, що ми хотіли. Як ми вже знаємо з попередніх уроків, оператор вилучення працює з «відформатовані даними», тобто він ігнорує всі прогалини, символи табуляції і символ нового рядка. Щоб прочитати весь вміст як є, без його розбивки на частині (як в прикладі вище), нам потрібно використовувати метод getline ():

#include #include #include #include // для використання exit () int main () (using namespace std; // ifstream використовується для читання вмісту файлів // Ми спробуємо прочитати вміст файлу SomeText.txt ifstream inf ( "SomeText.txt"); // Якщо ми не можемо відкрити файл для читання його вмісту if (! inf) (// Те виводимо наступне повідомлення про помилку і виконуємо exit () cerr<< "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть, что читать while (inf) { // То перемещаем то, что можем прочитать, в строку, а затем выводим эту строку на экран string strInput; getline(inf, strInput); cout << strInput << endl; } return 0; // Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл }

#include

#include

#include

#include // для використання exit ()

int main ()

using namespace std;

// ifstream використовується для читання вмісту файлів

ifstream inf ( "SomeText.txt");

// Якщо ми не можемо відкрити файл для читання його вмісту

if (! inf)

// Те виводимо наступне повідомлення про помилку і виконуємо exit ()

cerr<< "Uh oh, SomeText.txt could not be opened for reading!"<< endl ;

exit (1);

while (inf)

string strInput;

getline (inf, strInput);

cout<< strInput << endl ;

return 0;

// Коли inf вийде з зони видимості, то деструктор класу ifstream автоматично закриє наш файл

Результат виконання програми вище:

буферізованние висновок

Висновок в C ++ може бути буферизованного. Це означає, що все, що виводиться в файловий потік, не може відразу ж бути записаним на диск (в конкретний файл). Це зроблено, в першу чергу, з міркувань продуктивності. Коли дані буфера записуються на диск, то це називається очищенням буфера. Одним із способів очищення буфера є закриття файлу. У такому випадку весь вміст буфера буде переміщено на диск, а потім файл буде закритий.

Буферизація виводу зазвичай не є проблемою, але, при певних обставинах, вона може викликати проблеми у необережних новачків. Наприклад, коли в буфері зберігаються дані і програма передчасно завершує своє виконання (або в результаті збою, або шляхом виклику). У таких випадках деструктори класів файлового введення / виводу не виконуються, файли ніколи не закриваються, буфери не очищається і наші дані губляться назавжди. Ось чому гарною ідеєю є явне закриття всіх відкритих файлів перед викликом exit ().

Також буфер можна очистити вручну, використовуючи метод ostream :: flush ()або відправивши std :: flushв вихідний потік. Будь-який з цих способів може бути корисний для забезпечення негайної запису вмісту буфера на диск в разі збою програми.

цікавий нюанс: Оскільки std :: endl; також очищає вихідний потік, то його надмірне використання (що приводить до непотрібних очисткам буфера) може вплинути на продуктивність програми (так як очищення буфера в деяких випадках може бути витратною операцією). З цієї причини програмісти, які піклуються про продуктивність свого коду, часто використовують \ n замість std :: endl для вставки символу нового рядка у вихідний потік, щоб уникнути непотрібної очищення буфера.

Режими відкриття файлів

Що станеться, якщо ми спробуємо записати дані в уже існуючий файл? Повторний запуск програми вище (найперша) показує, що вихідний файл повністю перезаписується при повторному запуску програми. А що, якщо нам потрібно додати дані в кінець файлу? Виявляється, файлового потоку приймають необов'язковий другий параметр, який дозволяє вказати програмісту спосіб відкриття файлу. Як цього параметра можна передавати такі прапори(Які знаходяться в класі ios):

app- відкриває файл в режимі додавання;

ate- переходить в кінець файлу перед читанням / записом;

binary- відкриває файл в бінарному режимі (замість текстового режиму);

in- відкриває файл в режимі читання (за замовчуванням для ifstream);

out- відкриває файл в режимі запису (за замовчуванням для ofstream);

trunc- видаляє файл, якщо він вже існує.

Можна вказати відразу кілька прапорів шляхом використання.

ifstream за замовчуванням працює в режимі ios :: in;

ofstream за замовчуванням працює в режимі ios :: out;

fstream за замовчуванням працює в режимі ios :: in АБО ios :: out, що означає, що ви можете виконувати як читання вмісту файлу, так і запис даних в файл.

Тепер давайте напишемо програму, яка додасть два рядки в раніше створений файл SomeText.txt:

#include #include // для використання exit () #include int main () (using namespace std; // Передаємо прапор ios: app, щоб повідомити fstream, що ми збираємося додати свої дані до вже існуючих даних файлу, // ми не збираємося перезаписувати файл. Нам не потрібно передавати прапор ios :: out , // оскільки ofstream за замовчуванням працює в режимі ios :: out ofstream outf ( "SomeText.txt", ios :: app); // Якщо ми не можемо відкрити файл для запису даних if (! outf) (// Те виводимо наступне повідомлення про помилку і виконуємо exit () cerr<< "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } outf << "See line #3!" << endl; outf << "See line #4!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#include

#include // для використання exit ()

#include

int main ()

using namespace std;

// Передаємо прапор ios: app, щоб повідомити fstream, що ми збираємося додати свої дані до вже існуючих даних файлу,

// ми не збираємося перезаписувати файл. Нам не потрібно передавати прапор ios :: out,

// оскільки ofstream за замовчуванням працює в режимі ios :: out

ofstream outf ( "SomeText.txt", ios :: app);

// Якщо ми не можемо відкрити файл для запису даних

if (! outf)

// Те виводимо наступне повідомлення про помилку і виконуємо exit ()

cerr<< "Uh oh, SomeText.txt could not be opened for writing!"<< endl ;

exit (1);

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

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

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

Для роботи з файлами використовуються спеціальні типи даних, звані потоками.потік 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 ++ обробляються.

Останнє оновлення: 31.10.2015

Для роботи з каталогами в просторі імен System.IO призначені відразу два класи: Directory і DirectoryInfo.

клас Directory

Клас Directory надає ряд статичних методів для управління каталогами. Деякі з цих методів:

    CreateDirectory (path): створює каталог за вказаною шляху path

    Delete (path): видаляє каталог по зазначеному шляху path

    Exists (path): визначає, чи існує каталог по зазначеному шляху path. Якщо існує, повертається true, якщо не існує, то false

    GetDirectories (path): отримує список каталогів в каталозі path

    GetFiles (path): отримує список файлів в каталозі path

    Move (sourceDirName, destDirName): Переміщує каталог

    GetParent (path): отримання батьківського каталогу

клас DirectoryInfo

Даний клас надає функціональність для створення, видалення, переміщення і інших операцій з каталогами. Багато в чому він схожий на Directory. Деякі з його властивостей і методів:

    Create (): створює каталог

    CreateSubdirectory (path): створює підкаталог за вказаною шляху path

    Delete (): видаляє каталог

    Властивість Exists: визначає, чи існує каталог

    GetDirectories (): отримує список каталогів

    GetFiles (): отримує список файлів

    MoveTo (destDirName): переміщує каталог

    Властивість Parent: отримання батьківського каталогу

    Властивість Root: отримання кореневого каталогу

Подивимося на прикладах застосування цих класів

Отримання списку файлів і підкаталогів

string dirName = "C: \\"; if (Directory.Exists (dirName)) (Console.WriteLine ( "Підкаталоги:"); string dirs = Directory.GetDirectories (dirName); foreach (string s in dirs) (Console.WriteLine (s);) Console.WriteLine ( ); Console.WriteLine ( "Файли:"); string files = Directory.GetFiles (dirName); foreach (string s in files) (Console.WriteLine (s);))

Зверніть увагу на використання слешів в іменах файлів. Або ми використовуємо подвійний слеш: "C: \\", або одинарний, але тоді перед усією дорогою ставимо знак @: @ "C: \ Program Files"

створення каталогу

string path = @ "C: \ SomeDir"; string subpath = @ "program \ avalon"; DirectoryInfo dirInfo = new DirectoryInfo (path); if (! dirInfo.Exists) (dirInfo.Create ();) dirInfo.CreateSubdirectory (subpath);

Спочатку перевіряємо, а чи немає такої директорії, так як якщо вона існує, то її створити не можна буде, і додаток викине помилку. В результаті у нас вийде наступний шлях: "C: \ SomeDir \ program \ avalon"

Отримання інформації про каталог

string dirName = "C: \\ Program Files"; DirectoryInfo dirInfo = new DirectoryInfo (dirName); Console.WriteLine ($ "Назва каталогу: (dirInfo.Name)"); Console.WriteLine ($ "Повна назва каталогу: (dirInfo.FullName)"); Console.WriteLine ($ "Час створення каталогу: (dirInfo.CreationTime)"); Console.WriteLine ($ "Кореневий каталог: (dirInfo.Root)");

видалення каталогу

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

String dirName = @ "C: \ SomeFolder"; try (DirectoryInfo dirInfo = new DirectoryInfo (dirName); dirInfo.Delete (true); Console.WriteLine ( "Каталог видалений");) catch (Exception ex) (Console.WriteLine (ex.Message);)

String dirName = @ "C: \ SomeFolder"; Directory.Delete (dirName, true);

переміщення каталогу

string oldPath = @ "C: \ SomeFolder"; string newPath = @ "C: \ SomeDir"; DirectoryInfo dirInfo = new DirectoryInfo (oldPath); if (dirInfo.Exists && Directory.Exists (newPath) == false) (dirInfo.MoveTo (newPath);)

При переміщенні треба враховувати, що новий каталог, в який ми хочемо перемісити весь вміст старого каталогу, не повинен існувати.

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

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

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

файлової системоюназивається функціональна частина операційної системи, що забезпечує виконання операцій над файлами. Прикладами файлових систем є 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 (потік, "ФорматВвода", аргументи);



Сподобалася стаття? поділіться їй