Файл. Логическое описание. Физическое представление: буферная переменная, потоки и носители
file of T
(reset/rewrite/get/put/eof), в C - FILE*, поток байтов.
Физически файл живет на внешнем носителе: лента - строго
последовательно, диск - секторы и кластеры с быстрым доступом, флэш -
без позиционирования вовсе.
Что это такое
В прошлом уроке файл был математической абстракцией. Сегодня спускаемся на два нижних уровня: логическое описание - какими средствами языка файл реализуется, и физическое представление - как его компоненты реально лежат на носителе.
Логическое описание: Паскаль и C
В Паскале файловый тип описывается как file of T.
Ключевая идея - буферная переменная f^: окно
в один элемент, через которое программа смотрит на файл. В окне всегда текущая
компонента, загруженная в оперативную память. Операции: reset
(открыть на чтение), rewrite (на запись), get
(сдвинуть окно вперед), put (записать окно в файл)
и функция eof (конец файла).
В C описание прагматичнее и идет от ОС UNIX: файл - это
указатель на структуру файлового дескриптора FILE*,
а сам файл рассматривается как поток (stream) байтов,
текстовый или двоичный.
Различают также внутренние файлы - существуют только в ОЗУ на время работы программы - и внешние, которые хранятся на диске и имеют системное имя.
Физическое представление: зависит от носителя
Файл. Логическое описание. Физическое представление на устройствах
- Магнитная лента - классика последовательного файла: головка движется строго линейно, представление сплошное. Тот самый случай, когда физика носителя один в один совпадает со спецификацией.
- Магнитный диск (HDD) - быстрое позиционирование головки. Файл разбит на секторы и кластеры, которые могут лежать не подряд (фрагментация - цепное представление на уровне файловой системы), но ОС прячет это за абстракцией потока.
- Флэш-память - подвижных частей нет, доступ к блокам без задержек на позиционирование.
Буферизация
Обмен с диском в тысячи раз медленнее работы с ОЗУ, поэтому данные не пишутся
на носитель по одному байту: они копятся в буфере в оперативной памяти
и сбрасываются на диск разом. Закрытие файла (fclose) принудительно
сбрасывает буфер - вот почему забытый fclose может обернуться
пустым файлом на диске.
#include <stdio.h>
int main(void) {
/* Логическое описание: FILE* связывает программу
с физическим файлом через структуры ОС */
FILE *file = fopen("data.txt", "w");
if (file != NULL) {
/* Данные идут через буфер ОС на физический диск */
fprintf(file, "Hello, World!\n");
/* Закрытие файла сбрасывает буфер на диск */
fclose(file);
}
return 0;
}
buffering в open(). Блок with open(...) as f:
гарантирует закрытие файла (и сброс буфера) даже при ошибке - привычка,
которая в C соответствует дисциплине "каждому fopen - свой fclose".
Коротко: главное
- Логика в Паскале: file of T + буферная переменная f^ - окно в один элемент (reset/rewrite/get/put/eof).
- Логика в C: FILE* - поток байтов, текстовый или двоичный режим.
- Внутренние файлы живут в ОЗУ на время программы; внешние - на диске, с именем в ОС.
- Физика зависит от носителя: лента - строго последовательно, диск - секторы и кластеры, флэш - без позиционирования.
- Буферизация: данные копятся в ОЗУ и сбрасываются разом; fclose сбрасывает буфер.
Проверьте себя
Программа на C записала данные через fprintf и аварийно завершилась, не вызвав fclose. Почему файл на диске может оказаться пустым?