Создание и открытие файлов

Функция CreateFile может создать новый файл или открыть существующий. Необходимо указать имя файла, инструкции по созданию и другие атрибуты. Когда приложение создает новый файл, операционная система добавляет его в указанный каталог.

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

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

Когда приложение использует CreateFile, оно должно использовать параметр dwDesiredAccess , чтобы указать, будет ли оно выполнять чтение из файла, запись в файл( как чтение, так и запись) или ни то, ни другое. Это называется запросом режима доступа. Приложение также должно использовать параметр dwCreationDisposition , чтобы указать, какое действие следует предпринять, если файл уже существует. Это называется ликвидацией создания. Например, приложение может вызывать CreateFile с параметром dwCreationDisposition , для CREATE_ALWAYS, чтобы всегда создавать новый файл, даже если файл с таким же именем уже существует (таким образом, перезаписывает существующий файл). Успешно ли это будет выполнено, зависит от таких факторов, как атрибуты и параметры безопасности предыдущего файла (дополнительные сведения см. в следующих разделах).

Приложение также использует CreateFile , чтобы указать, нужно ли предоставить общий доступ к файлу для чтения, записи и того, и другого, или ни для того, ни другого. Это называется режимом общего доступа. Открытый файл, который не является общим (параметру dwShareMode присвоено нулевое значение), невозможно снова открыть ни приложением, которое его открыло, либо другим приложением, пока его дескриптор не будет закрыт. Это также называется монопольным доступом.

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

В следующей таблице показаны допустимые сочетания двух вызовов CreateFile с использованием различных режимов доступа и общего доступа (dwDesiredAccess, dwShareMode соответственно). Не имеет значения, в каком порядке выполняются вызовы CreateFile . Однако все последующие операции файлового ввода-вывода с каждым дескриптором по-прежнему будут ограничены текущими режимами доступа и общего доступа, связанными с этим дескриптором.

Первый вызов CreateFile Допустимые повторные вызовы CreateFile
GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_WRITE, FILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READ, FILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_WRITE, FILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READGENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READGENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READFILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READFILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE

Помимо стандартных атрибутов файла, можно также указать атрибуты безопасности, включив указатель на структуру SECURITY_ATTRIBUTES в качестве четвертого параметра CreateFile. Однако базовая файловая система должна поддерживать безопасность для этого, чтобы иметь какой-либо эффект (например, файловая система NTFS поддерживает ее, а различные файловые системы FAT — нет). Дополнительные сведения об атрибутах безопасности см. в разделе контроль доступа.

Приложение, создающее новый файл, может предоставить необязательный дескриптор файла шаблона, из которого CreateFile принимает атрибуты файла и расширенные атрибуты для создания нового файла.

Сценарии CreateFile

Существует несколько основных сценариев для инициации доступа к файлу с помощью функции CreateFile . Они представлены следующим образом:

  • Создание нового файла, если файл с таким именем еще не существует.
  • Создание нового файла, даже если файл с таким же именем уже существует, очистка его данных и запуск пустым.
  • Открытие существующего файла только в том случае, если он существует, и только без изменений.
  • Открытие существующего файла только в том случае, если он существует, усечение его до пустого.
  • Открытие файла всегда: как есть, если он существует, создание нового файла, если он не существует.

Эти сценарии управляются правильным использованием параметра dwCreationDisposition . Ниже приведена разбивка того, как эти сценарии сопоставляются со значениями для этого параметра и что происходит при их использовании.

При создании или открытии нового файла, если файл с таким именем еще не существует (параметру dwCreationDisposition присвоено значение CREATE_NEW, CREATE_ALWAYS или OPEN_ALWAYS), функция CreateFile выполняет следующие действия:

  • Объединяет атрибуты файла и флаги, заданные dwFlagsAndAttributes , с FILE_ATTRIBUTE_ARCHIVE.
  • Задает нулевую длину файла.
  • Копирует расширенные атрибуты, предоставленные файлом шаблона, в новый файл, если указан параметр hTemplateFile (переопределяет все флаги FILE_ATTRIBUTE_* , указанные ранее).
  • Задает флаг наследования, заданный элементом bInheritHandle , и дескриптором безопасности, заданным членом lpSecurityDescriptor параметра lpSecurityAttributes (SECURITY_ATTRIBUTES структуры), если он указан.

При создании нового файла, даже если файл с таким же именем уже существует (параметру dwCreationDisposition присвоено значение CREATE_ALWAYS), функция CreateFile выполняет следующие действия:

  • Проверяет текущие атрибуты файла и параметры безопасности для доступа на запись, если он запрещен.
  • Объединяет атрибуты и флаги файла, заданные dwFlagsAndAttributes , с FILE_ATTRIBUTE_ARCHIVE и существующими атрибутами файла.
  • Задает нулевую длину файла (то есть все данные, которые находились в файле, больше не доступны и файл пуст).
  • Копирует расширенные атрибуты, предоставленные файлом шаблона, в новый файл, если указан параметр hTemplateFile (переопределяет все флаги FILE_ATTRIBUTE_* , указанные ранее).
  • Задает флаг наследования, заданный членом bInheritHandle параметра lpSecurityAttributes (SECURITY_ATTRIBUTES структуры), если он указан, но игнорирует член lpSecurityDescriptorструктуры SECURITY_ATTRIBUTES .
  • В противном случае (т. е . CreateFile возвращает допустимый дескриптор), вызов Метода GetLastError приведет к ERROR_ALREADY_EXISTS кода, хотя для этого конкретного варианта использования это не является ошибкой как таковой (если вы намерены создать "новый" (пустой) файл вместо существующего).

При открытии существующего файла (dwCreationDisposition , для OPEN_EXISTING,OPEN_ALWAYS или TRUNCATE_EXISTING) функция CreateFile выполняет следующие действия:

  • Проверяет текущие атрибуты файла и параметры безопасности для запрошенного доступа, если он запрещен.
  • Объединяет флаги файлов (FILE_FLAG_*), заданные dwFlagsAndAttributes , с существующими атрибутами файла и игнорирует любые атрибуты файла (FILE_ATTRIBUTE_*), заданные dwFlagsAndAttributes.
  • Задает нулевую длину файла, только если параметру dwCreationDisposition присвоено значение TRUNCATE_EXISTING, в противном случае текущая длина файла сохраняется и файл открывается как есть.
  • Игнорирует параметр hTemplateFile .
  • Задает флаг наследования, заданный членом bInheritHandle параметра lpSecurityAttributes (SECURITY_ATTRIBUTES структуры), если он указан, но игнорирует член lpSecurityDescriptorструктуры SECURITY_ATTRIBUTES .

Атрибуты и каталоги файлов

Атрибуты файла являются частью метаданных, связанных с файлом или каталогом, каждый из которых имеет собственную цель и правила, определяющие, как их можно задать и изменить. Некоторые из этих атрибутов применяются только к файлам, а некоторые — только к каталогам. Например, атрибут FILE_ATTRIBUTE_DIRECTORY применяется только к каталогам. Он используется файловой системой для определения того, является ли объект на диске каталогом, но его нельзя изменить для существующего объекта файловой системы.

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

Функция CreateFile предоставляет параметр для настройки определенных атрибутов файла при создании файла. Как правило, эти атрибуты наиболее часто используются приложением во время создания файла, но не все возможные атрибуты файлов доступны для CreateFile. Некоторые атрибуты файла требуют использования других функций, таких как SetFileAttributes, DeviceIoControl или DecryptFile , после того как файл уже существует. В случае FILE_ATTRIBUTE_DIRECTORY функция CreateDirectory требуется во время создания, так как CreateFile не может создавать каталоги. Другие атрибуты файла, требующие специальной обработки , — это FILE_ATTRIBUTE_REPARSE_POINT и FILE_ATTRIBUTE_SPARSE_FILE, для которых требуется DeviceIoControl. Дополнительные сведения см. в разделе SetFileAttributes.

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

Состояние атрибута каталога Возможность переопределения наследования CreateFile для новых файлов
FILE_ATTRIBUTE_COMPRESSED задано.
Нет контроля. Используйте DeviceIoControl для очистки.
FILE_ATTRIBUTE_COMPRESSED не задано.
Нет контроля. Используйте DeviceIoControl для задания.
FILE_ATTRIBUTE_ENCRYPTED задано.
Нет контроля. Используйте DecryptFile.
FILE_ATTRIBUTE_ENCRYPTED не задано.
Можно задать с помощью CreateFile.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED задано.
Нет контроля. Используйте SetFileAttributes для очистки .
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED не задано.
Нет контроля. Используйте SetFileAttributes для задания.

Управление доступом

CreateFile

DeviceIoControl

Константы атрибута файла

Сжатие и распаковка файлов

Шифрование файлов

Функции управления файлами

Дескриптора и объекты

Обработка наследования

Открытие файла для чтения или записи

SetFileAttributes