Лекція 15. Керування буферізацією
| Сайт: | Навчально-інформаційний портал НУБіП України |
| Курс: | Основи програмування |
| Книга: | Лекція 15. Керування буферізацією |
| Надруковано: | Гість-користувач |
| Дата: | неділя, 15 лютого 2026, 19:42 |
1. Описання буферизації
Потоки за замовчуванням є буферизуємі, тобто при відкритті потоку з ним автоматично зв'язується область пам'яті, яку називають буфером. При читанні даних з потоку інформація розміщається у вхідному буфері й дані зчитуються з буфера. Коли весь буфер оброблений, у буфер зчитується наступний блок даних.
При записі зміст вихідного буфера записується у відповідний потік (буфер звільняється) коли буфер заповнений, або закривається відповідний потік, або коли програма успішно завершена.
Це підвищує ефективність програми, тому що обмін реально здійснюється не одним елементом даних, а цілими блоками. Буфери, створювані операційною системою, недоступні для користувача.
2. Функції буферизації
У мові програмування С існує можливість створювати не системні буфери для обміну, або робити обмін небуферизуємим.
Це можна здійснити за допомогою функцій:
1. void setbuf(stream, buffer);
2. int setvbuf(stream, buf, type, size).
0 – виділено;
<>0 – Помилка при виділенні.
Функція setvbuf дозволяє користувачеві керувати буферизацією і розміром буфера для потоку stream. Stream може посилатися на відкритий файл. Масив, на який указує buf, використовується як буфер, якщо він не є NULL, тобто потік не є буферизованим. Якщо потік буферизований, використовується тип, вказаний по type; цей тип може бути або _IONBF, або _IOFBF, або _IOLBF. Якщо використовується тип _IOFBF, розмір буфера визначається по size; якщо використовується тип _IOLBF або _IONBF, потік є НЕбуферизованим, а size і buf ігноруються.
Коли програма завершується аварійно, те вихідний буфер може бути не вивантаженим, що може привести до втрати інформації.
Для вивантаження буфера можна використовувати функцію:
int fflush (FILE *stream)
Якщо заданий потік stream відкритий для виводу, то вміст буфера, пов'язаного з потоком stream функції fflush, записується у відповідний файл. Якщо потік відкритий для введення, то функція fflush очищає вміст буфера. Після виклику функції потік залишається відкритим. Для небуферизованого потоку застосування цієї функції не ефективно.
int flushall() - функція записує вміст усіх буферів, пов'язаних з відкритими input потоками, у відповідні файли. Усі буфери, пов'язані з відкритими потоками, очищаються; наступна операція читання (якщо вона є) зчитує нові дані із вхідних файлів у буфер. Після виклику функції flushall усі потоки залишаються відкритими.
Дана функція повертає кількість відкритих потоків (вхідних і вихідних). У випадку помилки значення, що вертається, НЕМАЄ.
Слід зазначити, що потрібно обов'язково закривати файли, робота з якими проводиться через буфери користувача.
3. Текстовий та двійковий режим обміну
Можна відкривати потік у текстовому або двійковому режимі. Але ці режими мають певні особливості.
У текстовому режимі при введенні комбінація символів "повернути каретку - перевести строку" (\015 \012) перетвориться в один символ - перевести рядок. При висновку символ "перевести строку" перетвориться у два: \015, \012. Крім того, комбінація клавіш Ctrl+z (0х1а) сприймається як кінець файлу при висновку.
У двійковому режимі перетворення символів "ПК - ПС" не здійснюється.
Режим обміну з потоком можна змінювати після його відкриття. Для цього призначена функція нижнього рівня setmode. Як відзначалося на рівні потоків функції використовують покажчик потоку.
На нижньому рівні використовується інше поняття - дескриптор файлу (handle). Це є ціле число, яке зв'язується з файлом і використовується для посилань на даний файл. Так стандартні потоки stdin, stdout, stderr, stdaux, stdprn мають відповідні дескриптори 0,1,2,3,4.
int setmode (int handle, unsigned mode);( якщо функція повертає 0 - нормально, інакше –1)
handle – дескриптор файла, mode – режим.
Режим задається двома константами в файле <fcntl.h> O_BINARY двійковий
O_TEXT текстовий.
4. Інші функції обробки потоків
Для роботи з потоками можна використовувати й деякі інші функції. Для визначення кінця файлу призначена функція:
int feof (FILE *stream), яка передає нуль, якщо досягнуто кінець файлу при спробі прочитати символ, що випливає за останнім. Інакше її значення не нуль.
int ferror (FILE *stream) дозволяє встановити причину помилки читання або запису. Якщо 0 - помилки не було. Якщо трапилася помилка, то внутрішній індикатор помилки файлу буде встановлено доти, поки потік не буде закритим або rewind, або clearrer.
Змінити назву файлу можна за допомогою функції:
int rename (char *oldname, char *newname) і поміняти oldname на нову назву newname. Якщо така процедура здійснилася успішно, то функція передає нуль. Цю функцію можна використовувати для запису файлу до іншого каталогу, але в межах одного обладнання.
void rewind (stream), або void clearerr(stream) - яка записує в внутрішній індикатор помилки файлу нуль. Це ж здійснюється й при закритті потоку.
Знищити файл можна за допомогою функції:
int remove (const char *filename). Наступна спроба відкрити файл із таким іменем буде помилкою.
int fstat(handle,buffer) - одержує інформацію про відкритий файл, пов’язаний з даним handle, і запам'ятовує її в структурі, на яку вказує buffer.
buffer - структура, тип stat якої оголошений в <sys.h \ stat.h>, містить наступні поля.
На відміну від обміну з потоками, функції нижнього рівня здійснюють небуферизуємий і неформатовиний обмін і безпосередньо викликають засоби обміну операційної системи. Як відзначалося, на нижньому рівні з файлом зв'язується його дескриптор. Інтерфейсним для функції нижнього рівня є файл, який потрібно підключити до відповідної до програми.
Шрифти
Розмір шрифта
Колір тексту
Колір тла
Кернінг шрифтів
Видимість картинок
Інтервал між літерами
Висота рядка
Виділити посилання
Вирівнювання тексту
Ширина абзацу