Типы файлов: введение

Дмитрий Карпов

Источник: http://w3.misa.ac.ru/prof/techsupp/ftintro.htm

Как известно всем, кто занимался этим вопросом, информация обычно хранится на магнитных, а также на магнито-оптических и оптических носителях - жестких и сменных дисках. Жесткие диски и дисководы CD-ROM в большинстве имеют интерфейс IDE, реже - SCSI; дисководы используют интерфейс {MFM}; съемные дисководы типа Iomega ZIP помимо IDE и SCSI нередко подцепляются через LPT или COM-порты; в особо ответственных случаях используется энергонезависимая Flash-память. Все эти интерфейсы предельно примитивны и обеспечивают прямой доступ на наивозможно низком уровне для предоставления максимальной гибкости программному обеспечению (операционной системе) в размещении информации.

/* С одной стороны, мне бы хотелось, чтобы диск взял на себя больше работы; с другой стороны, учитывая современные тенденции, наверняка производители с самого начала реализовали бы самые примитивные схемы, а потом ради совместимости никто бы не решился что-либо изменить. Например, из-за такой совместимости диск IDE вынужден скрывать свою истинную конфигурацию, притворяясь, что у него на каждом треке одинаковое количество секторов. */

Все эти интерфейсы весьма неудобны как для пользователя, так и для программиста - в них нет ни учета занятого/свободного места, ни предоставления доступа по имени (во всех этих интерфейсах используется числовая адресация); к тому же в большинстве из них доступ производится только блоками размером от 256 до 8192 байт (по степеням двойки). Чтобы предоставить программисту и пользователю более удобный интерфейс, в меньшей степени зависящий от физической природы носителя, практически во все операционные системы включен такой компонент, как драйвер файловой системы (да обычно и не один, а несколько).

Технология современных файловых систем пошла от Unix: файл является набором байтов, которые можно читать как поодиночке, так и (что гораздо быстрее) пачками.

/* Для тех, кто интересуется историей, могу сообщить, что более древние файловые системы были организованы как базы данных, так что файл состоял из отдельных записей. Желающие могут посмотреть организацию работы с файлами в языке Fortran - она явно наследует принципы тех машин, на которых создавался Fortran. Многое оттуда унаследовано и языком Pascal, а вот язык C Кернигана и Ритчи имеет все признаки того, что он - радной для Unix. */

Но помимо данных, собственно содержащихся в файле, хотелось бы знать, для чего предназначены эти данные, как с ними можно обращаться.

Прежде всего, в любой файловой системе существуют два типа файлов:

  1. обычные, доступные программам напрямую;
  2. директории, содержащие списки других файлов и их атрибутов (списки, но не сами файлы), доступные только операционной системе (впрочем, ряд атрибутов доступен программам только-для-чтения, а то и для-изменения, но никак не напрямую);

плюс к тому в некоторых системах существуют специальные файлы, через которые осуществляется доступ к устройствам компьютера; в DOS примером могут быть файлы COM?, LPT?, PRN, CON, а в Unix - все файлы в директории /dev/.

Данные, содержащиеся в обычных файлах, тоже могут быть различны. Нередко тип данных можно определить прямо по их формату. Простейшая класификация:

В виде текста хранятся многие форматы - собственно текст, HTML, LaTex, программы на языках Basic, C, Fortran, Pascal и многих других, файлы редактора ChiWriter, почтовые сообщения (обычно формат MIME), /.../; а уж разнообразие двоичных форматов и вовсе неичислимо. Иногда формат файла можно угадать по его структуре или сигнатуре (характерному признаку, обычно специально внесенному в формат файла), но все это недостоверно (например, может оказаться, что файл, содержащий набор случайных чисел, содержит любую сигнатуру); так что хотелось бы иметь более четкий критерий. В Unix имеется утилита file, которая по содержимому файла (хотя, возможно, привлекаются соображения, основанные на имени файла и атрибутам доступа) на основании некоторых эмпирических правил определяет и сообщает пользователю тип файла.

Ситуация осложняется тем, что многие операционные системы должны работать с несвойственными для них файловыми системами имея прямой доступ к диску с неродной файловой системой или имея по сетИ доступ к серверу. При этом воникают проблемы уже на уровне имен файлов:

Кроме того, каждая файловая система имеет свои атрибуты доступа к файлам, зависящие от стратегии распределения прав пользователей, и свои дополнительные атрибуты, зависящие от фантази авторов систеы. Обычно разработчики стараются транслировать права доступа к файлу (перевести в формат, используемый в данной операционной системе) по определенным правилам Бывают и более сложные правила трансляции в зависимости от типа файла.

Простейший и наиболее универсальный (наименее платформенно-зависимый) способ состоит в том, чтобы зафиксировать тип данных в имени файла - имя ведь передается всегда и по возможности с наименьшими искажениями. По традиции тип файла отображают по возможности осмысленной аббревиатурой в конце имени файла, называемой "расширением имени файла" ("filename extension"), и для отделения используют точку '.' /* AcornOS, которая использует точку как разделитель имен директорий, там где Unix использует прямой слэш '/' а DOS/Windows - обратный '\', позволяет использовать вместо точки прямой или обратный слэш, но никто, кроме DOSFS, позволяющей работать с FAT-дискетами, не рассматривает слэши как разделители. */ Чаще всего стараются обойтись тремя символами в аббревиатуре; в RSX-11, CP/M и FAT это зафиксировано непосредственно в формате хранения имени файла, где точка является спец.символом, может присутствовать в имени файла только один раз - между основным именем и расширением, и не хранится в имени файла, а "вытекает из формата имени". В UFS (Unix), HPFS (OS/2), NTFS (Windows'NT) и NetWare нет такого ограничения, там точка является обычным символом имени файла, а ее специфическое значение распознается прикладными программами, если программист реализовал это в своей программе, но не отображается в формате файла. В VFAT работа с "длинными именами", не влезающими в формат "8.3" ("восемь букв на имя, точка, три буквы на расширение"), реализована довольно искусственно, для сохранения доступа программ, использующих простой FAT, в директории хранятся два имени - "короткое 8.3" и "длинное".

Иногда данные, имеющие какой-либо тип, последовательно "упаковываются" несколькими архиваторами; в этом случае возникают такие расширения как .tar.gz, обозначающее архив tar, подвергнутый gzip-компрессии (часто встречается в Unix), или .c.zip.uue, обозначающее пограмму на языке C, заархивированную программой zip и преобразованную uuencode для передачи по электронной почте без присущих ей искажений (выдумано мной для примера).

Я составил справочник соответствия расширений типам файлов по собственному опыту, литратуре и подсказкам заинтересованных посетителей моей страницы. Коллекция продолжает пополняться, и Вы можете принять в этом участие.

Основным недостатком использования расширений имени файла является как раз то, что тип файла определяется по имени файла

  1. Достаточно нелогично, что операция переименования влияет на атрибут, обозначающий тип содержимого - это провоцирует ошибки пользователей, вызванные опечатками при наборе на клавиатуре. Из-за такой ошибки файл может пропасть из списков, составляемых по типу файла, или, хуже того, появитьсмя в другом списке и вызвать проблемы в работе программ, полагающихся на расширение файла. Фактически раз переименование файла .koi.html в .win.txt не переводит файл из кодировки KOI8-r в Win1251 и из HTML-формата в простой текст, это является нарушением целостности данных; такие вещи допустимы в экстремальных случаях (когда администратор вынужден "лезть под капот" и вручную исправлять сбой), но недопустимо предоставлять любой программе, а тем более любому юзеру возможность без труда менять расширение имени файла без соответствующего изменения содержимого!
  2. Часто одно и то же расширение используется для совершенно различных типов файлов. Примером может служить .doc, обозначающий как просто документацию, так и файлы несовместимых между собой версий MS-Word для DOS, Windows'3.x (версии до шестой) и Windows'9x/NT (начиная с седьмой, именуемые также по году выпуска).

В Unix запускаемые файлы имеют специальный атрибут. Вообще говоря, транслировать этот атрибут другим операционным системам, даже Unix'ам и даже другим версиям того же Unix'а (особенно если отличаются первые цифры версий) довольно опасно - Unix-совместимость гарантирована только на уровне исходного кода и требует перекомпиляции. Формат двоичных запускаемых файлов никогда не бывает текстовым#, поэтому его нельзя перепутать с со скриптами - интерпретируемыми программами. Чтобы скрипт интерпретировался именно нужным интерпретатором, в его начало помещаетя строка

	#!/путь/shell [ключи]
которая определчяет тип скрипта (наиболее распространенные - sh, csh и прочие варианты командной оболочки, а также perl; особо одаренные, бывает, используют awk). Серьезный недостаток этого метода в том, что интерпретатор может находиться не в том месте, где его ожидал автор скрипта, или начинаются проблемы с версией интерпретатора, явно указанной в имени файла.

Acorn и Macintosh (Apple) используют специальное поле, в котором записывается в числовом виде тип файла. Чтобы разные авторы форматов файлов не вступали в противоречие друг с другом, используя одно и то же число для обозначения разных форматов, обе фирмы ведут учет используемых типов и если программист хочет, чтобы его программа беспроблемно использовалась широкими слоями юзеров, он должен зарегестрировать придуманный им тип данных, получив для него идентификатор. /* Аналогично Acorn распределяет системные вызовы SWI.*/ Macintosh имеет сструктуру типа ACL в NTFS, но хранит там не права доступа, а информацию о типе данных; Acorn использует два четырехбайтных поля, использовавшиеся в 8-битных машинах для информации об адресе загрузки и адресе запуска программы.

Сетевой протокол HTTP использует свой способ сообщить клиенту тип передаваемых данных (я сознательно говорю "тип данных", а не "тип файла" - передаваемые данные могут не содержаться в файле, а формироваться непосредственно по запросу). Способ называется MIME и используется во многих других местах, в частности, в электронной почте. Формат MIME довольно прост: в начале идет заголовок, состоящий из строк

	имя_параметра: значение [атрибуты]
затем пустая строка и собственно данные. В HTTP обязательно (а для другие могут обойтись и без этого) должна присутствовать строка
	Content-Type: тип/подтип
определяющая тип данных. Если тип - text, то в атрибутах часто передается кодировка, особенно если документ составлен на языке, использующем не латиницу, а собственный алфавит. Многие почтовые программы прямо жить не могут без
	MIME-Version: 1.0
Особо мне хочется отметить вариант
	Content-Type: multipart/подтип; boundary="строка"
где подтип - alternative (части содержат одно и то же в разных форматах) или mixed (совокупность данных разного формата), а "строка" обычно что-нибудь типа "----=_NextPart_000_0037_01BE808E.D9AC1F40" - уникальная для данного документа последовательность символов, не встречающаяся нигде, кроме разделителей. Разделителями являются
	--строка
а в конце всего идет
	--строка--
Каждый из разделов сам оформлен в формате MIME, разве что не требует "MIME-Version:", так что может в свою очередь содержать multipart данные.

Остался непроясненным вопрос о том, откуда составитель MIME-документа узнает о том, к какому типу относятся включенные в документ данные.


Ссылки:

Программы для работы с графикой: