WinAPI: Работа с файлами (основные функции)

Категорически всех приветствую! На этот раз в наше поле зрения попала группа API-функций для работы с файлами. Ибо как мне кажется что по мимо меня многие программисты сталкиваются с необходимостью их использования в своих программах. Но откровенно скажу в голове все эти функции в мести с их возможными параметрами и не упомнишь, и иметь возможность «вспомнить все» ;) прочитав эту статью очень не плохая затея. За семь и приступаю к рассмотрению оного =).

В этой статье мы рассмотрим следующие API-функции:

CreateFile
OpenFile
ReadFile
WriteFile
CloseFile
DeleteFile
CopyFile
FindFirstFile
FindNextFile
GetFileSize

Замечание

Но прежде чем приступить к дело, замечу, для случая когда действия над файлами происходят удаленно. За счет реализации в ОС Windows механизма прозрачного доступа к файлам, данные функции работают и с удаленными файлами, отличием является задание сетевого пути к файлу, а именно для С/С++ необходимо указывать путь в следующем формате: «\\\\имя_удаленного_компа\\путь_к_ файлу\\ имя_файла».

Пример:

Для Delphi необходимо указывать путь в следующем формате: «\\имя_удаленного_компа\путь_к_ файлу\имя_файла».

Пример:

Функция CreateFile

Функция создаёт указатель на новое устройство типа:

  • Файл
  • Канал
  • mailslot (почтовый канал)
  • комуникационный ресурс (например COM порт)
  • дисковые устройства (только для Windows NT)
  • консоли
  • директории (открывает их)

Все эти функции описаны в одном файле. Для С/С++ в хедере (заголовочный файл) winbase.h, для Delphi в модуле windows.pas. Чтобы использовать в своей программе эти функции, достаточно подключить их к своему проекту и вперед. Змечу, для тех кто кодит на С/С++ кроме winbase.h надо подключить еще windows.h.

Описание:

С/С++

Delphi

Теперь к главному, как создать файл? Делается это так:

C/C++

Delphi

Теперь рассмотрим используемые параметры:

  • параметры GENERIC_READ и GENERIC_WRITE определяют доступ на чтение и запись. Однако можно указать что то одно, в зависимости от ваших потребностей. Если в качестве этого параметра указать 0, то в этом случае функция отработает успешно, однако никакого доступа к файлу не получит. Этот вариант удобно использовать для теста существования файла.
  • параметры FILE_SHARE_WRITE or FILE_SHARE_READ общий доступ на чтение и запись к данному файлу. То есть файл будет доступен при одновременном использовании несколькими процессами.
  • следующий параметр — атрибут безопасности неопределен. То есть все дескрипторы будут доступны дочерним процессам вашего приложения.
  • параметр CREATE_NEW указывает на создание нового файла. Если файл с заданным именем существует, то будет возвращен код ошибки. Если использовать параметр CREATE_ALWAYS, то в этом случае, если файл существует, то он будет перезаписан.
  • параметр FILE_ATTRIBUTE_NORMAL определяет файлу стандартные атрибуты. А если указывать флаг FILE_FLAG_OVERLAPPED, то файл будет доступен в асинхронном режиме.
  • так как мы не используем шаблоны, то в качестве этого параметра указываем ноль.

Функция OpenFile

Данная функция, по сути своей, предназначена для открытия файлов или устройств. Функция OpenFile в случае успеха возвращает дискриптор (указатель) открываемого файла. В случае неудачи мы получим в качестве дискриптора значение INVALID_HANDLE_VALUE.

C/C++

Delphi

Теперь рассмотрим используемые параметры:

  • в качестве первого параметра указывается имя открываемого файла.
  • вторым параметром является специальная структура открываемого файла, в которую заносится полезная инфа о файле.
  • 3 параметр представляет собой совокупность флагов для работы с файлом.

Собственно, как открыть файл:

C/C++

Delphi

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

Функция ReadFile

Данная функция предназначена для чтения файлов или с устройств ввода/вывода. В случае успешного выполнения операции чтения, возвращается логическое значение true, иначе false. А функция GetLastError вернет ERROR_HANDLE_EOF.

C/C++

Delphi

Теперь поглядим рабочий пример:

C/C++

Delphi

Функция WriteFile

Данная функция предназначена для записи в файл или устройство ввода/вывода. С ней все аналогично что и с функцией ReadFile(). В случае успешного выполнения операции чтения, возвращается логическое значение true, иначе false. А функция GetLastError вернет ERROR_HANDLE_EOF.

C/C++

Delphi

f

Теперь поглядим рабочий пример:

C/C++

Delphi

Функция CloseFile

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

Теперь поглядим рабочий пример:

C/C++

Delphi

Функция DeleteFile

Эта функция так же не отличается особой сложностью. Данная функция удаляет файл, который указан в парамметре. Функция возвращает значение true если выполняется успешно. Иначе возвращает false, а код ошибки можно получить с помощью GetLastError.

C/C++

Delphi

Теперь поглядим рабочий пример:

C/C++

Delphi

Функция CopyFile

Основное назначение этой функции копирование файла. В случае успеха возвращает true, иначе — false. Код ошибки можно получить с помощью GetLastError.

C/C++

Delphi

Теперь поглядим рабочий пример:

C/C++

Delphi

Функция FindFirstFile

Данная функция запускает поиск в указанной директории. Функция возвращает указатель на найденный файл, если нет то возврат будет типа ERROR_NO_MORE_FILES.

C/C++

Delphi

Теперь рассмотрим парамметры подробней:

  • lpFileName — строка содержащая путь для поиска файла. Эта строка может указывать наконкретный файл типа ‘c:\filename.txt’ или может хранить шаблон ‘c:\*.*’. Если указывать шаблон, то это даёт возможность перечислить все файлы удовлетворяющие шаблону.
  • lpFindFileData — структура WIN32_FIND_DATA, в которую будет записана инфа о найденом файле.

Расмотрим структуру WIN32_FIND_DATA немного подробнее:

Атрибутами файла может быть комбинация из флагов:

  • FILE_ATTRIBUTE_ARCHIVE — архивный
  • FILE_ATTRIBUTE_COMPRESSED — сжатый
  • FILE_ATTRIBUTE_HIDDEN — скрытый
  • FILE_ATTRIBUTE_NORMAL — нормальный
  • FILE_ATTRIBUTE_OFFLINE — данные файла недоступны
  • FILE_ATTRIBUTE_READONLY — только для чтения
  • FILE_ATTRIBUTE_SYSTEM — системный
  • FILE_ATTRIBUTE_TEMPORARY — временный

Размер файла разложен на два байта. Чтоб получить полный размер файла нужно выполнить действие (FInfo.nFileSizeHigh * MAXDWORD) + FInfo.nFileSizeLow. Это не самый эффективный (эффективнее сдвигать), но самый понятный способ.

Теперь поглядим рабочий пример:

C/C++

Delphi

Функция FindNextFile

Данная функция продолжает поиск начатый функцией FindFirstFile(). Если очередной файл найден, то функция возвращает значение true, иначе возврат будет типа ERROR_NO_MORE_FILES.

C/C++

Delphi

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

Теперь поглядим рабочий пример:

C/C++

А теперь пример рекурсивного поиска файлов:

Delphi

Функция GetFileSize

Данная функция определяет размер файла, на который ссылается переданный указатель. Если размер файла меньше 4 Гб, то функция возвращает размер файла. Если размер файла больше 4Гб, то размер файла записан во втором парамметре. В случае возникновения исключения, будет возвращено значение типа INVALID_FILE_SIZE.

C/C++

Delphi

Теперь поглядим рабочий пример:

C/C++

Delphi

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

Понравилась статья? Поделиться с друзьями:
Комментариев: 7
  1. Freeeon

    В примере WriteFile написано ReadFile =/

  2. Владимир

    Здравствуйте!

    у меня такая проблема… есть файл 32 гига бинарный. записи строго по 8 байт….
    требуется в дельфи уметь читать любую запись 8 байт, при нужде ее изменить и записать
    назад. Стандартные процедуры не поддерживают такие размеры. помогите.

    Владимир.

    1. Кирилёв Сергей

      я не думаю что кто то возьмётся за такую работу, тем более бесплатно.

      1. lizz

        Ну почему сразу работу. Я думаю если кто может посоветовать в каком направлении копать, то здорово. Сам, увы, не сталкивался с таким, да и не дельфист вовсе.

        Кстати, у Яндекса в вопросах на должность python-разработчика тоже есть задание на работу с большими файлами. Я оптимального решения которое меня бы устраивало не придумал, но думаю ответ лежит где-то в смежной области с этим вопросом. :)

  3. Юрий Шерстяннин

    Пытаюсь процедурой WriteFile записать структуру диска на Flash (MBR, Boot, FAT и данные), ну, короче, практически образ. Все прекрасно до 63-го сектора (c 64 на диске начинается запись 1-го раздела), далее не пишет — процедура возвращает ошибку. Вероятно, это пространство оккупировано также какими-то процессами Windows. Есть ли способ все-же записать образ полностью?

  4. Юрий Шерстяннин

    Извиняюсь, уже нашел ответ на свой вопрос. ОС действительно не позволяет писать в области FAT, но позволяет в область MBR. Для того, чтобы писать в любое место необходимо демонтировать том, выполнить последовательность действий аналогичную той, которой меняют ОС на диске:
    1. Открыть том.
    2. Блокировать том.
    3. Форматировать том.
    4. Демонтировать том.
    5. Разблокировать том.
    6. Закрыть дескриптор тома.

    о чем явно сказано здесь:
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562(v=vs.85).aspx
    (ну, так сказать, кому это интересно).

  5. Вороной Толик (Узбекистан)

    Огромное спасибо!!!

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: