Работа с файлами windows api

Адаптивная, SEO подготовленная WordPress тема WordPress тема под вирусный контент и социальные сети

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

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

CreateFile
OpenFile
ReadFile
WriteFile
CloseFile
DeleteFile
CopyFile
FindFirstFile
FindNextFile
GetFileSize

Замечание

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

Пример:

DeleteFile(«\\\\comp1\\user1\\test\\test1.txt»);

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

Пример:

DeleteFile(«\\comp1\user1\test\test1.txt»);

Функция CreateFile

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

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

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

Описание:

С/С++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

HANDLE CreateFile(

LPCTSTR lpFileName, // Указатель на имя файла (устройства)

DWORD dwDesiredAccess, //Параметры доступа

DWORD dwShareMode, //Разделяемый доступ

LPSECURITY_ATTRIBUTES lpSecurityAttributes, //безопасность

DWORD dwCreationDistribution,// Описание

DWORD dwFlagsAndAttributes, // Атрибуты файла

HANDLE hTemplateFile // Файл шаблона

);

Delphi

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

function CreateFile(

lpFileName: PChar; // Указатель на имя файла (устройства)

dwDesiredAccess, //Параметры доступа

dwShareMode: DWORD; //Разделяемый доступ

lpSecurityAttributes: PSecurityAttributes; //безопасность

dwCreationDisposition, // Описание

dwFlagsAndAttributes: DWORD; // Атрибуты файла

hTemplateFile: THandle // Файл шаблона

): THandle; stdcall;

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

C/C++

{

Handle FileHandle;

FileHandle=CreateFile(«file1.txt»,GENERIC_READ |

GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_NEW,

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);

CloseHandle(FileHandle);

}

Delphi

var

FileHandle:THandle;

begin

FileHandle:=CreateFile(PChar(‘file1.txt’),GENERIC_READ or

GENERIC_WRITE, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, CREATE_NEW,

FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);

CloseHandle(FileHandle);

end;

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

  • параметры 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++

HFILE WINAPI OpenFile(

LPCSTR lpFileName,

LPOFSTRUCT lpReOpenBuff,

UINT uStyle

);

Delphi

function OpenFile(

lpFileName: LPCSTR, //имя файла (устройства)

lpReOpenBuff: TOFStruct, //специальная структура открываемого файла

uStyle: UINT //флаги доступа к файлу

): HFILE; stdcall;

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

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

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

C/C++

{

Handle FileHandle;

FileHandle= OpenFile(«Settings.ini», Buf, OF_Create |

OF_READWRITE | OF_SHARE_EXCLUSIVE);

CloseHandle(FileHandle);

}

Delphi

var

FileHandle:THandle;

begin

FileHandle:=OpenFile(PChar(‘Settings.ini’), Buf, OF_Create

Or OF_READWRITE Or OF_SHARE_EXCLUSIVE);

CloseHandle(FileHandle);

end;

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

Функция ReadFile

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

C/C++

BOOL ReadFile(HANDLE hFile, //собственно указатель на файл

LPVOID lpBuffer, // указатель на буфер — куда записываем считанные данные

DWORD nNumberOfBytesToRead, //объем считываемых данных, не может превышать размер буфера

LPDWORD lpNumberOfBytesRead, //фактический размер считанных данных

LPOVERLAPPED lpOverlapped // флаг режима доступа к файлу: асинхронный(FILE_FLAG_OVERLAPPED)

//или синхронный(NULL)

);

Delphi

function ReadFile(

hFile: THandle; //собственно указатель на файл

var Buffer; // указатель на буфер — куда записываем считанные данные

nNumberOfBytesToRead: DWORD; //объем считываемых данных, не может превышать размер буфера

var lpNumberOfBytesRead: DWORD; //фактический размер считанных данных

lpOverlapped: POverlapped// флаг режима доступа к файлу: асинхронный(FILE_FLAG_OVERLAPPED)

//или синхронный(nil)

): BOOL; stdcall;

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

C/C++

{

Handle FileHandle;

char Buf[1000];

...

ReadFile(FileHandle, Buf, sizeof(buf),NULL);

...

}

Delphi

var

FileHandle:THandle;

Buf:array[1..1000] of char;

begin

...

ReadFile(FileHandle, Buf, sizeof(buf),NULL);

...

end;

Функция WriteFile

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

C/C++

BOOL WriteFile(HANDLE hFile, //собственно указатель на файл

LPVOID lpBuffer, // указатель на буфер — откуда записываем данные в файл

DWORD nNumberOfBytesToWrite, //объем записываемых данных

LPDWORD lpNumberOfBytesWrite, //фактический размер записанных данных

LPOVERLAPPED lpOverlapped // флаг режима доступа к файлу: асинхронный(FILE_FLAG_OVERLAPPED)

//или синхронный(NULL)

);

Delphi

f

unction WriteFile(

hFile: THandle; //собственно указатель на файл

var Buffer; // указатель на буфер — откуда записываем данные в файл

nNumberOfBytesToWrite: DWORD; //объем записываемых данных

var lpNumberOfBytesWrite: DWORD; //фактический размер записанных данных

lpOverlapped: POverlapped// флаг режима доступа к файлу: асинхронный(FILE_FLAG_OVERLAPPED)

//или синхронный(nil)

): BOOL; stdcall;

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

C/C++

{

Handle FileHandle;

char Buf[1000];

...

ReadFile(FileHandle, Buf, sizeof(buf),NULL);

...

}

Delphi

var

FileHandle:THandle;

Buf:array[1..1000] of char;

begin

...

ReadFile(FileHandle, Buf, sizeof(buf),NULL);

...

end;

Функция CloseFile

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

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

C/C++

{

Handle FileHandle;

FileHandle= OpenFile(«Settings.ini», Buf, OF_Create |

OF_READWRITE | OF_SHARE_EXCLUSIVE);

...

CloseHandle(FileHandle);

}

Delphi

var

FileHandle:THandle;

begin

FileHandle:=OpenFile(PChar(‘Settings.ini’), Buf, OF_Create

Or OF_READWRITE Or OF_SHARE_EXCLUSIVE);

...

CloseHandle(FileHandle);

end;

Функция DeleteFile

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

C/C++

BOOL WINAPI DeleteFile(

LPCTSTR lpFileName // имя файла, который надо удалить

);

Delphi

function DeleteFile(

lpFileName: PChar; // имя файла, который надо удалить

): BOOL; stdcall;

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

C/C++

{

...

DeleteFile(«C:\Temp\test.txt»);// если указать только

// имя файла, то будет осуществлена попытка удалить файл из папки откуда была запущена программа

...

}

Delphi

begin

...

DeleteFile(‘C:\Temp\test.txt’);// если указать только

// имя файла, то будет осуществлена попытка удалить файл из папки откуда была запущена программа

...

end;

Функция CopyFile

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

C/C++

BOOL CopyFile(

LPCTSTR lpExistingFileName,// Указатель на файл, который надо копировать

LPCTSTR lpNewFileName, // Указатель на имя файла, куда надо копировать

BOOL bFailIfExists //если указать true, то в случае существования такого файла,

// он будет перезаписан, если false — то произойдет ошибка.

);

Delphi

function CopyFile(

lpExistingFileName, // Указатель на файл, который надо копировать

lpNewFileName: PChar; // Указатель на имя файла, куда надо копировать

bFailIfExists: BOOL //если указать true, то в случае существования такого файла,

// он будет перезаписан, если false — то произойдет ошибка.

): BOOL; stdcall;

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

C/C++

{

...

CopyFile(«C:\Temp\test1.txt»,«C:\Temp\test2.txt», true); // если указать только

// имя файла, то все действия будут выполнены в папке из которой запущена прога

...

}

Delphi

begin

...

CopyFile(‘C:\Temp\test1.txt’,‘C:\Temp\test2.txt’, false);// если указать только

// имя файла, то все действия будут выполнены в папке из которой запущена прога…

end;

Функция FindFirstFile

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

C/C++

HANDLE FindFirstFile(

LPCTSTR lpFileName, // Строка содержащая путь для поиска файлов.

LPWIN32_FIND_DATA lpFindFileData // Информация о найденном файле

);

Delphi

function FindFirstFile(

lpFileName: PChar; // Строка содержащая путь для поиска файлов.

var lpFindFileData: TWIN32FindData // Информация о найденном файле

): THandle; stdcall;

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

typedef struct _WIN32_FIND_DATA {

DWORD dwFileAttributes; // Атрибуты файла

FILETIME ftCreationTime; // Время создания

FILETIME ftLastAccessTime; //Время последнего доступа

FILETIME ftLastWriteTime; //Время последней записи в файл

DWORD nFileSizeHigh; //Верхний байт размера файла

DWORD nFileSizeLow; //Нижний байт размера файла

DWORD dwReserved0; //Зарезервировано

DWORD dwReserved1; //Зарезервировано

TCHAR cFileName[ MAX_PATH ]; //Имя файла

TCHAR cAlternateFileName[ 14 ]; //Имя файла для отображения в DOS (8:3)

} 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++

{

WIN32_FIND_DATA sss;

HANDLE f;

f = FindFirstFile(«C:\*.*», &sss);

...

FindClose(f);

}

Delphi

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

var

sss: TWIN32FindData;

f:THandle;

begin

...

f:=FindFirstFile(PChar(‘C:\*.*’), sss);

...

Windows.FindClose(f);

end;

Функция FindNextFile

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

C/C++

BOOL FindNextFile(

HANDLE hFindFile, // Указатель на файл из предыдущего поиска

LPWIN32_FIND_DATA lpFindFileData // Информация об очередном найденном файле

);

Delphi

function FindNextFile(

hFindFile: THandle; // Указатель на файл из предыдущего поиска

var lpFindFileData: TWIN32FindData // Информация об очередном найденном файле

): BOOL; stdcall;

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

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

C/C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

{

WIN32_FIND_DATA sss;

HANDLE f;

f = FindFirstFile(«C:\*.*», &sss);

if(f != INVALID_HANDLE_VALUE)

do{

...

}while(FindNextFile(f,&sss));

FindClose(f);

}

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

Delphi

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

function find(put: string):integer;

var

sss: TWIN32FindData;

f:THandle;

result:Boolean;

begin

...

f:=FindFirstFile(PChar(‘C:\*.*’), sss);

if f<>INVALID_HANDLE_VALUE then

begin

result:=true;

while(result)do

begin

if not((sss.cFileName = ‘.’)or(sss.cFileName = ‘..’)) then

if (sss.dwFileAttributes and faDirectory) > 0 then

find(put+\+sss.cFileName)

else

writeln(sss.cFileName);

...

result:=FindNextFile(f,sss);

end;

end;

Windows.FindClose(f);

end;

Функция GetFileSize

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

C/C++

DWORD GetFileSize(

HANDLE hFile, // Указатель на файл

LPDWORD lpFileSizeHigh // старший байт размера файла, в качестве

// этого парамметра можно указать NULL

);

Delphi

function GetFileSize(

hFile: THandle; // Указатель на файл

lpFileSizeHigh: Pointer //старший байт размера файла, в качестве

// этого парамметра можно указать nil

): DWORD; stdcall;

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

C/C++

{

DWORD FileSize;

Handle f;

...

FileSize=GetFileSize(f,NULL);

...

}

Delphi

var

FileSize:DWORD;

f:THandle;

begin

...

FileSize:=GetFileSize(f,nil);

...

end

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

Из предыдущих постов, посвященных WinAPI, мы научились настраивать Visual Studio и узнали, как в нем писать простые консольные приложения. Следующим маленьким шажком в изучении WinAPI будет освоение работы с файлами.

Для этого нелегкого дела нам понадобятся следующие процедуры:

CreateFile(szName, dwAccess, dwShareMode, lpSecurityAttributes,
           dwCreationDisposition, dwFlags, hTemplateFile);

В Windows для того, чтобы открыть или создать файл, нужно вызвать процедуру, имеющую целых семь аргументов. К счастью, большинство из них приходится использовать крайне редко. Аргумент szName задает имя файла, а dwAccess — желаемый доступ к файлу, обычно это GENERIC_READ, GENERIC_WRITE или оба значения, объединенные логическим или. Параметр dwShareMode определяет, что могут делать с файлом другие процессы, пока мы с ним работаем. Возможные значения — FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE и их комбинации, однако часто этот параметр просто устанавливают в ноль. Параметр dwCreationDisposition определяет, как именно мы хотим открыть файл, может быть, например, CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING, OPEN_ALWAYS. О семантике этого хозяйства нетрудно догадаться самостоятельно. С помощью dwFlags можно указать дополнительные свойства файла, например, хранить ли его в зашифрованном или сжатом виде, или сказать, что файл является скрытым, временным или системным. Обычно сюда передают FILE_ATTRIBUTE_NORMAL. Наконец, про lpSecurityAttributes и hTemplateFile сейчас знать не нужно, сюда можно смело передавать NULL.

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

ReadFile(hFile, lpBuff, dwBuffSize, &dwCount, NULL);

Чтение из файла в буфер lpBuff размером dwBuffSize. В переменную dwCount записывается реальное количество прочитанных байт. Последний опциональный аргумент называется lpOverlapped и о нем сейчас знать не нужно.

WriteFile(hFile, lpBuff, dwBuffSize, &dwCount, NULL);

Аргументы и семантика процедуры WriteFile полностью аналогичны ReadFile.

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

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

#include <windows.h>

#define MAX_TRIAL_RUNS 5

const TCHAR szCounterFileName[] = L«counter.dat»;
const TCHAR szMsgTmpl[] = L«Вы запустили программу в %d-й раз. %s.»;
const TCHAR szCheckOk[] = L«Все в порядке, продолжайте работу»;
const TCHAR szCheckFailed[] = L«Триал истек, купите полную версию»;

DWORD ReadCounter() {
  DWORD dwCounter, dwTemp;
  HANDLE hFile = CreateFile(szCounterFileName, GENERIC_READ, 0, NULL,
                           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if(INVALID_HANDLE_VALUE == hFile) {
    return 1;
  }
  ReadFile(hFile, &dwCounter, sizeof(dwCounter), &dwTemp, NULL);
  if(sizeof(dwCounter) != dwTemp) {
    CloseHandle(hFile);
    return 1;
  }
  CloseHandle(hFile);
  return dwCounter;
}

VOID WriteCounter(DWORD dwCounter) {
  DWORD dwTemp;
  HANDLE hFile = CreateFile(szCounterFileName, GENERIC_WRITE, 0, NULL,
                           CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if(INVALID_HANDLE_VALUE == hFile) {
    return;
  }
  WriteFile(hFile, &dwCounter, sizeof(dwCounter), &dwTemp, NULL);
  CloseHandle(hFile);
}

int main() {
  TCHAR szMsg[256];
  DWORD dwCounter = ReadCounter();
  LPCWSTR lpCheckResult = dwCounter > MAX_TRIAL_RUNS ?
                          szCheckFailed : szCheckOk;
  wsprintf(szMsg, szMsgTmpl, dwCounter, lpCheckResult);
  MessageBox(0, szMsg, L«Сообщение», 0);

  if(dwCounter <= MAX_TRIAL_RUNS) {
    WriteCounter(dwCounter+1);
  }

  ExitProcess(0);
}

Как обычно, программа также успешно компилируется при помощи MinGW и запускается под Wine.

В качестве домашнего задания можете попробовать модифицировать программу так, чтобы она выводила время, когда производились все ее запуски. Для этого вам понадобятся процедуры GetLocalTime, SetFilePointer и GetFileSizeEx. Если это задание покажется вам слишком простым, попробуйте найти информацию о том, как при помощи процедур, упомянутых в этой заметке, (1) написать консольное приложение и (2) открыть диск C: на чтение, словно он является обычным файлом.

Если у вас есть дополнения или возникли вопросы, смелее пишите комментарии, не стесняйтесь!

Дополнение: Рекурсивный поиск файлов с использованием WinAPI

Метки: C/C++, WinAPI.

В лекции рассматривается использование функций библиотеки (C++): CreateFile(), CopyFile(), MoveFile(), DeleteFile(), ReadFile(), WriteFile(), UnlockFile(), LockFile() и CloseHandle().

Материалы по данной теме имеются так же в лекции про файлы.

Содержание лекции:

Создание файлов
Для создания нового или открытия существующего файла используется функция CreateFile. При использовании функции CreateFile необходимо указать, предполагается чтение или запись в файл или и то и другое. Также необходимо указать, необходимые действия в случае наличия файла на диске или его отсутствия (например, перезаписывать файл, если он существует и создавать новый, если – нет). Также функция CreateFile позволяет указать возможность разделения файла с другими приложениями (одновременного чтения/записи нескольких приложений в файл). Если некоторое приложение монополизировало доступ к файлу на чтение и/или запись, то никакое другое приложение не сможет читать и/или писать в файл, пока первое его не закроет.

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

Функция CreateFile среди прочих объектов позволяет обращаться к файлам и каналам (pipes). При обращении к каналам функция CreateFile позволяет создавать клиентское подключение к именованным каналам, находящимся в режиме ожидания подключения. Серверная часть канала создаётся функцией CreateNamedPipe. Одно приложение может создавать множество клиентских подключений к каналу, но к одному экземпляру канала может подключаться только одно приложение (Стоит отметить, что возможно существование нескольких экземпляров именованных каналов с одинаковыми именами).

Функция CreateFile имеет следующий прототип:

HANDLE CreateFile(
  LPCTSTR lpFileName, // file name
  DWORD dwDesiredAccess, // access mode
  DWORD dwShareMode, // share mode
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
  DWORD dwCreationDisposition, // how to create
  DWORD dwFlagsAndAttributes, // file attributes
  HANDLE hTemplateFile // handle to template file
);

lpFileName:

[in] Указатель на строку, содержащую имя объекта для создания или открытия (имя файла, путь к файлу, имя канала и пр.). Если имя задается литеральной константой, то следует поместить её в макрос TEXT() или поставить L перед открывающей кавычкой. Например, TEXT(«C:\\tmp.txt») или L»C:\\tmp.txt»

dwDesiredAccess:

[in] Описание желаемого режима доступа к файлу. Существует возможность передачи большого количества различных флагов. Нас интересуют флаги GENERIC_READ, GENERIC_WRITE и их объединение. При доступе к каналам следует учитывать режим создания канала сервером. Если сервер создал канал для записи, то клиент открывает его для чтения и наоборот. Если сервер создал канал для чтения и записи, то клиент может открыть его как для чтения, так и для записи.

dwShareMode:

[in] Определяет режим разделения объекта 
0 – приложение открывает файл для монопольного доступа. Последующие обращения на открытие данного файла будут безуспешными, пока данных дескриптор не будет закрыт. Для разделения доступа к файлу могут использоваться следующие ключи (один или вместе):
FILE_SHARE_READ – разрешены лишь последующие операции открытия только на чтение.
FILE_SHARE_WRITE – разрешены лишь последующие операции открытия только на запись.
lpSecurityAttributes 
[in] Указатель на сруктуру SECURITY_ATTRIBUTES, которая определяет возможность наследования дескриптора дочерними процессами. Можно передавать NULL – это значит, что дескриптор не может быть наследован (для наших приложений этого достаточно).

dwCreationDisposition:

[in] Определяет то, какие действия необходимо предпринять в случаях, если файл существует и если файл не существует. Этот параметр должен иметь одно из следующих заначений:
Значение Пояснение
CREATE_NEW Создаёт файл. Вызов заканчивается неудачей, если файл существует.
CREATE_ALWAYS Создаёт новый файл. Если файл существует, то его содержимое и атрибуты будут стёрты.
OPEN_EXISTING Открытие файла. Если файл не существует, то вызов закончится неудачей. 
OPEN_ALWAYS

Открывает файл. Если файл не существует, то он будет создан.
TRUNCATE_EXISTING Открывает файл, размер которого обнуляется. Файл должен открываться как минимум с режимом доступа GENERIC_WRITE. Если файл не существует, то вызов будет неудачен.

dwFlagsAndAttributes:

[in] Позволяет задавать файловые атрибуты (только для чтения, скрытый, системный и пр.). Также позволяет сообщать операционной системе желаемое поведение при работе с файлами. Например, запись в файл без буферизации (FILE_FLAG_NO_BUFFERING и FILE_FLAG_WRITE_THROUGH); оптимизация для неупорядоченного доступа (FILE_FLAG_RANDOM_ACCESS); открытие для асинхронного ввода/вывода (FILE_FLAG_OVERLAPPED).

Возвращаемое значение:

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

Для копирования файлов используется функция

CopyFile

:

BOOL CopyFile(
  LPCTSTR lpExistingFileName, // имя существующего файла
  LPCTSTR lpNewFileName, // имя нового файла
  BOOL bFailIfExists // действие, если файл существует TRUE – ошибка
  // FALSE — перезаписывать
);

В случае успеха возвращается ненулевое значение.

Для переименования файлов и директорий используется функция

MoveFile

:

BOOL MoveFile(
  LPCTSTR lpExistingFileName, // имя файла
  LPCTSTR lpNewFileName // новое имя файла
);

В случае успеха возвращается ненулевое значение.

Для удаления существующих файлов используется функция

DeleteFile:

BOOL DeleteFile(
  LPCTSTR lpFileName // имя удаляемого файла
);

В случае успеха возвращается ненулевое значение.

Чтение/запись в файл:
Каждый открытый файл имеет файловый указатель (file pointer), который указывает позицию следующего файла, который будет записан/прочтен. При открытии файла его файловый указатель перемещается на начало файла. После прочтения/записи очередного файла система перемещает файловый указатель. Файловый указатель можно перемещать, используя функцию SetFilePointer.
Для чтения/записи в файл используются функции ReadFile и WriteFile, при этом необходимо, чтобы файл был открыт на чтение и на запись соответственно. 

Функция

ReadFile

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

BOOL ReadFile(
  HANDLE hFile, // дескриптор файла
  LPVOID lpBuffer, // буфер данных
  DWORD nNumberOfBytesToRead, // количество байт для прочтения
  LPDWORD lpNumberOfBytesRead, // количество фактически прочитанных байт
  LPOVERLAPPED lpOverlapped // указатель на структуру, используемую при
  // асинхронном чтении
);

Параметры:

hFile:

[in] Дескриптор читаемого файла. Должен быть открыт с доступом GENERIC_READ.

lpBuffer:

[out] Указатель на буфер, принимающий данные из файла. 

nNumberOfBytesToRead:

[in] Задаёт количество байт, которые необходимо прочитать из файла. 

lpNumberOfBytesRead:

[out] Указатель на переменную, которая принимает количество реально прочитанных байт.

lpOverlapped:

[in] Укзатель на структуру OVERLAPPED. При не асинхронном доступе следует передавать NULL.

Возвращаемое значение

:
Если выполнение функции произошло успешно, то возвращается ненулевое значение. Если возвращено ненулевое значение, но прочитано 0 байт, значит файловый указатель стоял на конце файла перед операцией чтения.

Функция

WriteFile

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

BOOL WriteFile(
  HANDLE hFile, // дескриптор файла
  LPCVOID lpBuffer, // буфер данных
  DWORD nNumberOfBytesToWrite, // количество байт для записи
LPDWORD lpNumberOfBytesWritten,// количество фактически записанных байт
  LPOVERLAPPED lpOverlapped // указатель на структуру, используемую при
  // асинхронном чтении
);

Параметры:

hFile:

[in] Дескриптор файла, в который производится запись. Должен быть открыт с доступом GENERIC_WRITE.

l

pBuffer:

[in] Указатель на буфер, содержащий данные, которые необходимо записать. 

nNumberOfBytesToWrite:

[in] Задаёт количество байт, которые необходимо записать в файл. 

lpNumberOfBytesWritten:

[out] Указатель на переменную, которая принимает количество реально записанных байт.

lpOverlapped:

[in] Укзатель на структуру OVERLAPPED. При не асинхронном доступе следует передавать NULL.

Возвращаемое значение:

Если выполнение функции произошло успешно, то возвращается ненулевое значение.

Блокировка файлов:
Т.к. система позволяет более чем одному приложению открывать файл и писать в него, приложения не должны одновременно писать в одну область файла. Эта проблема может быть решена путем временного блокирования части файла. Функция LockFile позволяет приложению получить в монопольное пользования определённое количество байт в файле. Отрезок заблокированных байт может выходить за текущий конец файла. Все попытки сторонних приложений обратиться к заблокированному участку файла потерпят неудачу.
Приложение может файл с помощью функции

UnlockFile

.

BOOL LockFile(
  HANDLE hFile, // дескриптор файла
  DWORD dwFileOffsetLow, // младшее слово смещения начала отрезка
  DWORD dwFileOffsetHigh, // старшее слово смещения начала отрезка
  DWORD nNumberOfBytesToLockLow, // младшее слово длины отрезка
  DWORD nNumberOfBytesToLockHigh // старшее слово длины отрезка
);

Параметры:

hFile:

[in] Дескриптор файла, в который производится запись. Должен быть открыт с доступом GENERIC_READ или GENERIC_WRITE (или обоими).

dwFileOffsetLow:

[in] Определяет младшее слово смещения начала блокируемого отрезка относительно начала файла.

dwFileOffsetHigh:

[in] Определяет старшее слово смещения начала блокируемого отрезка относительно начала файла. Не равно нулю, если смещение относительно начала более чем 232 байт.

nNumberOfBytesToLockLow:

[in] Определяет младшее слово длины блокируемого отрезка.

nNumberOfBytesToLockHigh:

[in] Определяет старшее слово длины блокируемого отрезка. Не равно нулю, если длина отрезка более 232 байт или 4 ГБ.

Возвращаемое значение:

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

Функция UnlockFile позволяет разблокировать участок файла, ранее заблокированный функцией LockFile.

BOOL UnlockFile(
  HANDLE hFile, // дескриптор файла
  DWORD dwFileOffsetLow, // младшее слово смещения начала отрезка
  DWORD dwFileOffsetHigh, // старшее слово смещения начала отрезка
  DWORD nNumberOfBytesToUnlockLow, // младшее слово длины отрезка
  DWORD nNumberOfBytesToUnlockHigh // старшее слово длины отрезка
);

Параметры данной функции аналогичны параметрам функции LockFile.

Возвращаемое значение:

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

Для оптимального использования ресурсов операционной системы приложение должно закрывать ненужные файлы с помощью функции

CloseHandle

. Файлы, открытые на момент завершения приложения, закрываются автоматически.

BOOL CloseHandle(
  HANDLE hObject // Дескриптор объекта (файла, канала и пр.)
);

Возвращаемое значение:

Если выполнение функции произошло успешно, то возвращается ненулевое значение.




Добавил: COBA (12.03.2009) | Категория: Операционные системы

Просмотров: 17606 | Загрузок: 1449
| Рейтинг: 3.8/4 |

Теги: программирование, файлы, WinAPI

Programming Examples

Are you a Programmer or Application Developer or a DBA? Take a cup of coffee, sit back and spend few minutes here :)


1.  Introduction to CreateFile Win32 API

In this article, we will look at the example of using the CreateFile, ReadFile, WriteFile and OpenFile win32 API functions with an MFC Dialog based application. Win32 is a very rich API that supplies many functions and MFC is a Framework wrapped over those functions to form a logical working unit. Win32 API library is in a native format that means it is in C style (Procedural Approach) whereas MFC is an OOPS based Framework API. OK, let us start with the sample.

2. About Win32 File Copy Example

The below screenshot shows the sample application we will create in this article:

Win32 CreateFile Example
Win32 CreateFile Example

We set up the sample to copy the file text from source location to target location. The OS provides support for this plain file content copy work and this example is just for demo purpose. However, one can extend the task to transfer source content to target by skipping some words or adding something to the word, etc.

In the above sample, we can mention the filename to copy in the Source File Path. The Destination File Path text field holds target file name in which we need a copy of the source file content. The CopyFile Win32 API will do this task easily. However, in this article we will try the Win32 file processing functions CreateFile Win32, ReadFile, WriteFile and OpenFile. The sample is created using the VC++ Dialog-Based application.

Creating the dialog-based application is shown in the below video.

Once the dialog-based application is set up, we add control variables to the Edit boxes. The below video shows the steps:

3. Coding For The Win32 File API

3.1 Declaration of File Handles

First, we declare the win32 handles to the files and these handles are
hcopysource,
hCopyDest. Next, we declare the variables
bytes_read,
bytes_written to store the number of bytes read and written depending on the file processing operation. We also declare a char array to store the data read from the file temporarily.

//Sample 01: Declarations Required

HANDLE hcopysource, hCopyDest;

DWORD bytes_read, bytes_written;

CHAR buffer [4095];

3.2 Read User Input

Next, we read user input from the text box control variables to the string variables
Source_file,
Dest_file. The call to the
GetWindowText function returns the text key-in in the text boxes.

//Sample 02: Get the User input

CString Source_file, Dest_file;

m_edit_ctrl_from.GetWindowText(Source_file);

m_edit_ctrl_to.GetWindowText(Dest_file);

3.3 CreateFile API & OPEN_EXISTING

The below code snippet uses the Win32 API function
CreateFile
to open the file entered by the user. The
OPEN_EXISTING
tag will tell the API to open the file when it already exits and fail otherwise. Once we open the file content which we will copy, we store the handle in the hcopysource. The
GENERIC_READ
flag for
CreateFile tells that we are going to open the file for reading purpose.

//Sample 03: Create the Source File

hcopysource = ::CreateFile (Source_file, GENERIC_READ,

  FILE_SHARE_READ, NULL, OPEN_EXISTING,

  FILE_ATTRIBUTE_NORMAL, NULL);

if (hcopysource == INVALID_HANDLE_VALUE)

         AfxMessageBox(«Unable to Open Source File»);

3.4 CreateFile API & CREATE_ALWAYS

In the previous section, we stored a file handle for copy source. The same way we can store the destination file handle. Here it is expected that the file does not exist in the destination folder and we always try to create the file as a new file in the location specified. The flag
GENERIC_WRITE
tells that we will use this file for writing something on it. The
CREATE_ALWAYS
attribute tells that we will always create the file. If it doesn’t exist in the destination location, the API will create a new file and if it is there in that location, then the function will just open it. Therefore, the tag always creates the file and gives back the handle. Note we use the same
CreateFile Win32 API for both reading and writing.

//Sample 04: Create Destination File

hCopyDest = ::CreateFile (Dest_file, GENERIC_WRITE,

  0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,

  NULL);

if (hcopysource == INVALID_HANDLE_VALUE)

         AfxMessageBox(«Unable to Destination Source File»);

3.5 File Copy Using ReadFile & WriteFile

In this section, we write code to perform the file copy using
ReadFile
&
WriteFile
Win32 API functions. We use
ReadFile Win32 API to read the data from the source file. Once the call succeeded, we will get the read content in the buffer variable. When the file content is over 4095 bytes, we will read its content in batches by making use of the loop. This means in each batch, we will read  4095 or less (That will be last read). The
bytes_read  variable passed to
ReadFile Win32 will tell us how many bytes are read from the source file. Say, for example, the file has 5000 bytes of data, and the first read batch will read all 4095 bytes and next batch will read the remaining 5 bytes in the next iteration. This way, we use the
bytes_read variable when writing the data to the destination file using the API function WriteFile.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//Sample 05: Read the Source file content in a batch of

//4095 or Lesser, then write to destination file

while (::ReadFile(hcopysource, buffer, 4095, &amp;bytes_read, NULL)

  &amp;&amp; bytes_read > 0)

{

         ::WriteFile(hCopyDest, buffer, bytes_read,

         &amp;bytes_written, NULL);

         if (bytes_read != bytes_written)

         {

                 AfxMessageBox(«Something Gone wrong while writing «

                  «to destination. Aborting the operation»);

                 ::CloseHandle(hcopysource);

                 ::CloseHandle(hCopyDest);

                 return;

         }

}

AfxMessageBox(«File contents copied to destination»);

3.6 Cleanup

After completing the file copy action using ReadFile and WriteFile API functions, we close the file HANDLES. Then we display a message stating the content of the file copied to the target location.

//Sample 06: Do the Clean-Up work

m_edit_ctrl_from.SetWindowText(«»);

m_edit_ctrl_to.SetWindowText(«»);

::CloseHandle(hcopysource);

::CloseHandle(hCopyDest);

Below given video shows how the sample perform the file copy operation using the Win32 API Functions:

 

Source Code: Download Win32 CreateFile Example From Google Drive

Categories: Win32

Tags: CreateFile, CREATE_ALWAYS, GENERIC_WRITE, GERERIC_READ, OPEN_EXISTING, ReadFile, WriteFile

Аннотация: На этой лекции Вы познакомитесь с файловыми операциями ввода-вывода с использованием API Windows, а также научитесь программировать «каркас» приложения Windows по предложенным автором шаблонам. Это поможет Вам впоследствии легко создавать простейшие программы Windows.

9.1. Файловые операции ввода-вывода с использованием WinAPI

9.1.1. Особенности файловых операций в Microsoft Windows

Файловые операции в операционной системе Microsoft Windows отличаются от файловых операций MS-DOS следующим:

  1. Заявлена переносимость всех файловых операций в операционных системах MS Windows на последующие версии. Это значит, что если строго следовать рекомендациям Microsoft Windows в описании её файловых функций, программа будет «эффективно компилироваться» как для платформы Win16, так и для платформы Win32 и Win64;
  2. Указанные ниже функции позволяют создавать текстовые файлы размером как до 64 Кбайт, так и до 2 Гбайт (напомню, что в MS-DOS максимальный размер текстового файла — 64 Кбайт);
  3. Имена файлов теперь могут писаться в кодировке ANSI с использованием «длинных имён» файлов. В MS-DOS возможно именовать файлы только в кодировке OEM с «короткими» именами файлов и каталогов;
  4. Содержимое файла, созданного средствами Windows, сразу и целиком читается в оперативную память компьютера, и уже потом анализируются другими функциями (например, sscanf). В MS-DOS Вы могли вводить и выводить файлы последовательно по строкам, по формату и по записям (используя функции fges, getc, fscanf и др.). Используемый в Windows способ чтения-записи является более «безопасным» для обработчика данных и операционной системы;
  5. Следствие вышесказанного. В операционной системе Microsoft Windows нужно открывать файл, осуществлять все операции чтения записи и закрывать файл в пределах обработчика одного сообщения из очереди сообщений Windows. В MS-DOS Вы могли вначале программы открыть файл, где-то в теле программы осуществить операции ввода-вывода, и закрыть файлы в конце программы. В Windows этот способ не работает — программа в ней выполняется не в том порядке, в котором записаны действия, а в том порядке, в каком поступают программе системные вызовы. Вследствие этого, по «логике программы», закрытие файла может произойти прежде, чем операция записи-чтения из файла. Естественно, произойдёт «отказ системы» со всеми вытекающими неприятными последствиями;
  6. Функции открытия файлов возвращают операционной системе намного больше информации, чем «обычные» функции открытия файлов MS-DOS. При этом принимать решение, использовать или нет эту расширенную информацию, может сам программист;
  7. «Стандартными средствами открытия файлов» в Microsoft Windows невозможно открытие файлов для добавления информации в конец файла.… Наверное, Вы поняли почему. Если нет — отвечаю: при чтении всего файла в буфер в конец файла можно записать любую информацию, с тем чтобы затем её сбросить на диск под тем же именем, и дополнительного режима открытия файлов не требуется;
  8. Помимо функций файлового ввода-вывода Microsoft Windows Вы также можете использовать аналогичные функции ввода-вывода MS-DOS, с указанными Выше ограничениями. Но учтите, что функциями ввода-вывода MS-DOS (всё равно, являются ли они консольными, потоковыми или другими), нельзя выводить текст на экран, принтер, COM порт, а также вводить данные с клавиатуры;

Примечание: операции потокового вывода на экран и ввода с клавиатуры можно также осуществить и в Windows, указав опцию в IDE при создании проекта «консольное приложение Windows». Этот вопрос Вы можете изучить самостоятельно [38].

9.1.2. Функции создания и закрытия файлов методами Win API

Для создания, открытия и закрытия файлов Windows API использует следующие функции:

ФУНКЦИЯ OpenFile
СИНТАКСИС: HFILE WINAPI OpenFile( lpszFileName, lpOpenStruct, fuMode)

LPCSTR lpszFileName — путь к файлу (в виде дальнего указателя на строку в кодировке ANSI, заканчивающуюся двоичным нулём);

OFSTRUCT FAR* lpOpenStruct — адрес структуры OFSTRUCT, заполняемой при первом открытии файла;

UINT fuMode — режим работы и атрибуты файла;

НАЗНАЧЕНИЕ: Открывает файл и связывает с ним дескриптор файла;
ОПИСАНИЕ: Функция предназначена для создания, открытия, повторного открытия и удаления файлов. В имени файла допускается указывать символы шаблона, такие как «*» и «?». Параметр fuMode используется для определения действий, выполняемых функцией OpenFile, а также задаёт атрибуты файла. Когда функция OpenFile вызывается в первый раз для открытия файла, она заполняет структуру OFSTRUCT, описанную в приложении №1 (смотри пункт 9.4 данной лекции);
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: Функция возвращает идентификатор файла, который можно (и нужно) использовать во всех последующих операциях с файлом, или -1 при ошибке;
ПЕРЕНОСИМОСТЬ: Версии MS Windows 3.0 и старше;
ФУНКЦИЯ _lopen
СИНТАКСИС: HFILE WINAPI _lopen( LPCSTR lpszFileName, int fuOpenMode)

LPCSTR lpszFileName — путь к файлу (в виде дальнего указателя на строку в кодировке ANSI, заканчивающуюся двоичным нулём);

int fnOpenMode — параметр определяет режим, в котором открывается файл;

НАЗНАЧЕНИЕ: Открывает файл и связывает с ним дескриптор файла (упрощённая версия);
ОПИСАНИЕ: Функция предназначена для открытия, повторного открытия файлов. В имени файла допускается указывать символы шаблона, такие как «*» и «?». Параметр fuMode используется для определения действий, выполняемых функцией _lopen ;
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: Функция возвращает идентификатор файла, который можно (и нужно) использовать во всех последующих операциях с файлом, или HFILE_ERROR при ошибке;
ПЕРЕНОСИМОСТЬ: Версии MS Windows 3.0 и старше;
ФУНКЦИЯ _lclose
СИНТАКСИС: HFILE WINAPI _lclose( hf )

HFILE hf — дескриптор закрываемого файла;

НАЗНАЧЕНИЕ: Закрывает файл, связанный с соответствующим дескриптором;
ОПИСАНИЕ: Закрывает файл с дескриптором hf ;
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: Если файл закрыт успешно, _lclose возвращает нулевое значение. При ошибке возвращается значение: HFILE_ERROR ;
ПЕРЕНОСИМОСТЬ: Версии MS Windows 3.0 и старше;
ФУНКЦИЯ _lcreat
СИНТАКСИС: HFILE _lcreat( lpszFileName, fuAttribute)

LPCSTR lpszFileName — путь к файлу (в виде дальнего указателя на строку в кодировке ANSI, заканчивающуюся двоичным нулём);

int fuAttribute — переменная позволяет определить атрибуты создаваемого файла;

НАЗНАЧЕНИЕ: Создаёт файл средствами Win API;
ОПИСАНИЕ: Это более простая, чем OpenFile, функция для создания новых файлов. Имя файла не должно содержать метасимволов шаблона. Если указанный первым параметром файл не существует, функция _lcreat создаёт его и открывает для записи, возвращая его дескриптор файла. Если файл существует, он обрезается до нулевой длины, и затем открывается для чтения и записи;
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: Идентификатор созданного файла;
ПЕРЕНОСИМОСТЬ: Версии MS Windows 3.0 и старше;

Отличие функции OpenFile от функции _lopen заключается в поддержке ей расширенной информации о файле, передаваемой структуре OFSTRUCT, и в большем числе поддерживаемых флагов команды. Информацию о флагах функций OpenFile, _lcreate и _lopen смотри в таблице 9.1. Описание функций смотри в приложении №I к данной лекции (пункт 9.4).

Таблица
9.1.
Флаги и режимы открытия файлов средствами WinAPI.

Константа Описание
ФУНКЦИЯ OpenFile
OF_READ Файл открывается только для чтения.
OF_WRITE Файл открывается только для записи.
OF_READWRITE Файл открывается для чтения и записи.
OF_SHARE_COMPAT Открытие файла в режиме совместимости. В этом режиме несколько приложений могут одновременно открыть файл, причём все эти приложения должны открывать файл в режиме совместимости.
OF_SHARE_EXCLUSIVE Файл открывается в монопольном режиме. Для всех других приложений доступ к этому файлу на чтение и запись запрещён.
OF_SHARE_DENY_WRITE После открытия файла к нему запрещается доступ со стороны других приложений на запись.
OF_SHARE_DENY_READ После открытия файла к нему запрещается доступ со стороны других приложений на чтение.
OF_SHARE_DENY_NONE Для открываемого файла не запрещается доступ к файлу ни на чтение, ни на запись.
OF_PARSE Если указан этот флаг, функция OpenFile не выполняет никаких других действий, кроме заполнения структуры OFSTRUCT.
OF_DELETE Уничтожение существующего файла.
OF_VERIFY Если указан этот флаг, то функция OpenFile сравнивает время и дату, записанную в структуре OFSTRUCT, со временем и датой изменений указанного файла. Если обнаружено несоответствие, функция OpenFile возвращает значение HFILE_ERROR.
OF_SEARCH Операционная система выполняет поиск файла в каталогах даже в том случае, когда текстовая строка, указанная параметром lpszFileName, содержит полный путь к файлу.
OF_PROMPT Если указан этот флаг, то в случае невозможности найти указанный файл Windows выдаёт диалоговую панель с предложением вставить в дисковод A: дискету с файлом. Это флаг используется очень редко.
OF_CANCEL Данный флаг указывается вместе с флагом OF_PROMPT. Если он указан, то в описанную выше диалоговую панель будет добавлена кнопка «Cancel» для отмены открытия файла. Приложение при этом получит код ошибки, соответствующий ненайденному файлу, а пользователь – возможность выйти из затруднительного положения, в которое он попадает при отсутствии дискеты с нужным файлом.
OF_CREATE выполняется создание нового файла. Если указанный файл существует, то он обрезается до нулевой длины.
OF_EXIST При указании этого флага функция OpenFile вначале открывает файл, а потом сразу же его закрывает. Эта операция может быть использована для того, чтобы убедиться в существовании указанного файла на диске.
OF_REOPEN Этот флаг используется при повторном открытии файла на основе информации, хранящейся в структуре OFSTRUCT.
ФУНКЦИЯ _lopen
OF_READ Файл открывается только для чтения.
OF_WRITE Файл открывается только для записи.
OF_READWRITE Файл открывается для чтения и записи.
OF_SHARE_COMPAT Открытие файла в режиме совместимости. В этом режиме несколько приложений могут одновременно открыть файл, причём все эти приложения должны открывать файл в режиме совместимости.
OF_SHARE_EXCLUSIVE Файл открывается в монопольном режиме. Для всех других приложений доступ к этому файлу на чтение и запись запрещён.
OF_SHARE_DENY_WRITE После открытия файла к нему запрещается доступ со стороны других приложений на запись.
OF_SHARE_DENY_READ После открытия файла к нему запрещается доступ со стороны других приложений на чтение.
OF_SHARE_DENY_NONE Для открываемого файла не запрещается доступ к файлу ни на чтение, ни на запись.
ФУНКЦИЯ _lcreat
0 Нормальный файл, для которого разрешено выполнение операций чтения и записи
1 Этот файл можно открыть только для чтения
2 Скрытый файл
3 Системный файл

  • Работа с файлами linux из windows
  • Работа с обновлениями windows 10 очень долго что делать завершено 100
  • Работа с командной строкой для чайников windows
  • Работа с обновлениями windows 10 очень долго грузится
  • Работа с томами windows 10