Работа с файлами
Модуль управления файлами — один из наиболее устоявшихся компонентов операционных систем, отвечающий за обмен данными между программой и различными внешними устройствами. Он обеспечивает ввод и вывод данных, представленных во внешнем или внутреннем формате, временное хранение результатов расчета на внешних носителях и их последующее использование в повторных сеансах или в других программах, прием и передачу данных по каналам связи, просмотр и редактирование некоторых наборов данных, управление различными периферийными устройствами на логическом и физическом уровнях и т.п. Вообще говоря, это — достаточно сложное, разветвленное и постоянно развивающееся программное хозяйство, требующее знаний не только библиотечных функций по управлению файлами в той или иной операционной системе и соответствующей среде программирования, но и умения программировать на языке ассемблера, понимания временной последовательности реально происходящих процессов и многое другое.
Однако в большинстве случаев программистам приходится иметь дело с весьма ограниченным набором операций по запоминанию и извлечению данных, расположенных на жестких или гибких дисках. А эта работа, по существу, сводится к четырем-пяти следующими операциями:
- создание новых или уничтожение существующих файлов;
- выделение ресурсов и приведение файла в состояние готовности к обмену (именно это скрывается за термином открыть файл);
- чтение (ввод из файла) или запись (вывод в файл) очередной порции данных;
- перемещения указателя файла в начало нужной порции данных;
- возврат выделенных ресурсов и завершение неоконченных операций (этому соответствует термин закрыть файл).
Несмотря на кажущуюся простоту перечисленных операций, при работе с ними приходится учитывать форматы представления данных и структуры их хранения в оперативной памяти и на диске.
Дисковые файлы организованы в иерархическую структуру данных, вершиной которых является корневой каталог логического диска. Обычно такую структуру называют деревом по аналогии с обычным деревом с его корнем, основным стволом, ветвями и листьями. В программировании принято переворачивать обычные деревья с ног на голову. В корневом каталоге хранится информация обо всех элементах первого уровня — подкаталогах и файлах. Каждый из этих элементов имеет имя, которое в среде Windows может быть длинным, содержать русские буквы и даже пробелы. В каталоге запоминаются дисковый адрес, определяющий начало расположения соответствующего элемента, длина набора данных, дата его создания или последнего обновления и атрибуты, регулирующие способ доступа к данным и их видимость. Корневой каталог (каталог 0-го уровня) и подкаталоги следующих уровней занимают на диске непрерывное адресное пространство, тогда как файлы данных могут быть разбросаны порциями фиксированной длины — кластерами. Кластер образуется несколькими идущими подряд секторами, физическая емкость каждого равна 512 байтам. В зависимости от способа организации данных на винчестере (FAT12, FAT16, FAT32 и др.) и емкости винчестера размер кластеров может быть разным, но для хранения данных файлу всегда предоставляют целое число кластеров. Последовательность кластеров, выделенных файлу и необязательно следующих подряд, регистрируется в таблице распределения дискового пространства — FAT (File Allocation Table — таблица распределения файлов). Каталог ссылается на начальный кластер файла, а в соответствующей позиции FAT находится ссылка на продолжение цепочки данных. Последний кластер с данными, принадлежащими файлу, помечается специальным кодом — признаком конца файла (EOF — End-Of-File).
С точки зрения внутренней организации данных в дисковом файле и, соответственно, методов доступа к ним различают текстовые (строковые) и двоичные наборы данных.
В текстовых файлах числовая и строковая информация представлена цепочками символов переменной длины, в которых используются те или иные разделители данных (запятые, пробелы, кавычки) в пределах одной строки и управляющие коды, разграничивающие строки. Система управления файлами поддерживает последовательный доступ к строкам (порциям) таких данных. При этом после k-той строки читается или записывается (k+1)-я строка. Обмен с текстовыми файлами сопровождается прямыми или обратными преобразованиями числовой информации, что требует дополнительного времени и, как правило, сопряжено с увеличением объема занимаемой внешней памяти. Так, например, длинные целые числа в машинном формате занимают 4 байта, тогда как для символьной записи достаточно большого числа может потребоваться до 11 байт в строке. Плюс разделительные байты, которые должны быть вставлены между числами. Кроме того, системные программы должны анализировать каждый байт, участвующий в последовательном обмене, на предмет обнаружения признаков конца строки или конца файла. Зато символьное представление информации не зависит от типа компьютера и используемой операционной системы. Поэтому символьные данные могут быть переданы другим вычислительным средствам или отправлены по каналам связи абоненту, работающему на такой же или другой платформе (под этим термином имеют в виду процессор и/или операционную систему другого типа).
Двоичные файлы хранят информацию в том же виде, в котором она находилась и в оперативной памяти. Поэтому здесь экономится время обмена (никаких преобразований данных не происходит) и не требуется дополнительной памяти на диске. Более того, в двоичных файлах становится возможной операция по перемещению указателя файла на любую порцию данных, что позволяет обмениваться данными не только последовательно, но и в произвольном порядке. Иногда такой доступ называют прямым (Direct Access), иногда — случайным (Random Access). Для работы с двоичными файлами системы программирования обычно предлагают два варианта обмена. В первом случае содержимое файла рассматривается как набор записей одинакового размера, и такая запись ассоциируется с соответствующим типом данных (Type-End Type в VB, struct в C++, record в Паскале). Во втором случае пользователю разрешен обмен порциями произвольной длины. Но со структурой данных в очередной порции программа должна разбираться сама.
