Продолжаем дружно вспоминать WinAPI. В отличие от всех предыдущих заметок сегодня мы напишем первую программу, которая делает что-то действительно полезное. А именно, позволяет найти файл на жестком диске по части его имени.
В этом нам помогут следующие процедуры и структуры данных.
Процедура GetLogicalDrives возвращает битовую маску, по которой можно судить, какие диски есть в системе. Например, если 0-ой бит установлен в единицу, значит диск «A:» есть, иначе его нет. Аналогично, 1-ый бит соответствует диску «B:», 2-ой — диску «C:», и так далее до 25-го бита.
FindFirstFile(szPath, &fdFindData);
В качестве аргументов принимает строку типа «C:\windows\*.exe» и указатель на структуру WIN32_FIND_DATA. В случае успеха процедура возвращает хэндл, соответствующий поиску, а в fdFindData записывается информация о первом найденном файле — его имя, размер, атрибуты, время создания и так далее. В случае ошибки возвращается INVALID_HANDLE_VALUE.
FindNextFile(hFind, &fdFindData)
Принимает хэндл, полученный от FindFirstFile, и указатель на WIN32_FIND_DATA. Если FindNextFile вернул TRUE, значит в fdFindData записана информация о следующем файле. Если FALSE, значит все файлы, соответствующие маске, были перечислены.
Когда поиск завершен, FindClose закрывает хэндл, полученный от FindFirstFile.
Теперь с помощью перечисленных процедур, а также процедур, с которыми мы с вами познакомились в заметке Пишем простое консольное приложение на чистом WinAPI, не представляет труда написать программу, которая рекурсивно ищет файлы на всех дисках в системе, выводя те имена файлов, в которых содержится заданная в качестве аргумента подстрока:
#include <windows.h>
#include <shlwapi.h>
#define STRLEN(x) (sizeof(x)/sizeof(x[0]) — 1)
VOID ProcessFoundFile(HANDLE CONST hStdOut, LPWSTR CONST szPath,
WIN32_FIND_DATA CONST * CONST fdFindData,
LPWSTR CONST lpSearch) {
TCHAR szEnd[] = L«\r\n«;
DWORD dwTemp;
if(NULL != StrStrI(fdFindData->cFileName, lpSearch)) {
WriteConsole(hStdOut, szPath, lstrlen(szPath), &dwTemp, NULL);
WriteConsole(hStdOut, szEnd, STRLEN(szEnd), &dwTemp, NULL);
}
}
VOID FindFirstFileFailed(HANDLE CONST hStdOut, LPWSTR CONST szPath) {
TCHAR CONST szMsgTmpl[] = L«FindFirstFile() failed, «
L«GetLastError() = %d, szPath = %s\r\n«;
TCHAR szMsg[MAX_PATH*2];
DWORD dwTemp;
wsprintf(szMsg, szMsgTmpl, GetLastError(), szPath);
WriteConsole(hStdOut, szMsg, lstrlen(szMsg), &dwTemp, NULL);
}
VOID RecursiveSearch(HANDLE CONST hStdOut, LPWSTR szPath,
LPWSTR CONST lpSearch) {
WIN32_FIND_DATA fdFindData;
HANDLE hFind;
TCHAR * CONST lpLastChar = szPath + lstrlen(szPath);
lstrcat(szPath, L«*»);
hFind = FindFirstFile(szPath, &fdFindData);
*lpLastChar = ‘\0‘;
if(INVALID_HANDLE_VALUE == hFind) {
FindFirstFileFailed(hStdOut, szPath);
return;
}
do {
if((0 == lstrcmp(fdFindData.cFileName, L«.»)) ||
(0 == lstrcmp(fdFindData.cFileName, L«..»))) {
continue;
}
lstrcat(szPath, fdFindData.cFileName);
if(fdFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
lstrcat(szPath, L«\\«);
RecursiveSearch(hStdOut, szPath, lpSearch);
} else {
ProcessFoundFile(hStdOut, szPath, &fdFindData, lpSearch);
}
*lpLastChar = ‘\0‘;
} while(FindNextFile(hFind, &fdFindData));
FindClose(hFind);
}
VOID SearchOnAllDrives(HANDLE CONST hStdOut, LPWSTR CONST lpSearch) {
TCHAR szCurrDrive[] = L«A:\\«;
TCHAR szPath[MAX_PATH+1];
DWORD i, dwDisksMask = GetLogicalDrives();
for(i = 0; i < 26; i++) {
if(dwDisksMask & 1) {
lstrcpy(szPath, szCurrDrive);
RecursiveSearch(hStdOut, szPath, lpSearch);
}
dwDisksMask >>= 1;
szCurrDrive[0]++;
}
}
INT main() {
DWORD dwTemp;
INT nArgs = 0;
LPWSTR CONST lpCmd = GetCommandLine();
LPWSTR CONST * CONST lpArgs = CommandLineToArgvW(lpCmd, &nArgs);
HANDLE CONST hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONST TCHAR szUsage[] = L«Usage: find.exe <part-of-file-name>\r\n«;
if(nArgs < 2) {
WriteConsole(hStdOut, szUsage, STRLEN(szUsage), &dwTemp, NULL);
} else {
SearchOnAllDrives(hStdOut, lpArgs[1]);
}
LocalFree((PVOID)lpArgs);
ExitProcess(0);
}
Чтобы эта программа успешно заработала, нужно кое-что поменять в свойствах нашего шаблонного проекта. Во-первых, тип приложения нужно изменить с GUI на CLI. Во-вторых, в свойствах проекта нужно найти Linker → Input → Additional Dependencies, и прописать там «shlwapi.lib» без кавычек. Зачем это нужно, будет рассказано чуть ниже. Также в свойствах проекта нужно указать аргументы, передаваемые программе при ее запуске из IDE. Для этого идем в Debugging → Command Arguments и пишем там, например, «.txt».
Если теперь скомпилировать и запустить программу, вы увидите примерно следующее:
В приведенном выше коде есть несколько тонких моментов. Во-первых, как вы могли заметить, в нем активно используется макрос CONST. Он определен в файле windef.h как:
Как большие специалисты по Си (вы же прочитали Кернигана и Ритчи, как я совевтовал?), вы, конечно же, прекрасно знаете, для чего нужно ключевое слово const. Но чисто на всякий случай освежим эти знания. Ключевое слово const говорит о том, что переменная является неизменяемой. Например, если написать:
HANDLE CONST hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
… а затем попытаться присвоить переменной hStdOut новое значение, компилятор откажется компилировать программу. Когда в дело вступают указатели, все становится чуточку интереснее. Проще всего показать это на примерах:
// неизменяемый указатель на массив неизменяемых LPWSTR
LPWSTR CONST * CONST lpArgs = CommandLineToArgvW(lpCmd, &nArgs);
// неизменяемый указатель на массив изменяемых TCHAR’ов
TCHAR * CONST lpLastChar = szPath + lstrlen(szPath);
// изменяемый указатель на массив неизменяемых TCHAR’ов
// TCHAR CONST * lpLastChar = …
Вместо «HANDLE CONST» также можно писать «CONST HANDLE». Учитывая, что в Си, как известно, можно с легкостью прострелить себе ногу, по возможности следует использовать const как можно чаще. Даже несмотря на то, что из-за него становится несколько сложнее читать код.
Во-вторых, вы могли обратить внимание на использование процедуры StrStrI. Как нетрудно догадаться, она предназначена для сравнения строк без учета регистра. Данная процедура экспортируется динамической библиотекой shlwapi.dll, поэтому нам пришлось написать в коде #include <shlwapi.h>
и в свойствах проекта указать, чтобы линковщик использовал библиотеку shlwapi.lib.
Наконец, в-третьих, наверняка вам не дает покоя следующая проверка:
if((0 == lstrcmp(fdFindData.cFileName, L«.»)) ||
(0 == lstrcmp(fdFindData.cFileName, L«..»))) {
continue;
}
Так сделано, потому что наряду с обычными файлами и каталогами, FindFirstFile и FindNextFile возвращают информацию о специальных каталогах «.» и «..», которые являются ссылками на текущий и родительский каталоги соответственно. Такая проверка гарантирует, что наш рекурсивный алгоритм не скушает весь стек, обращаясь к каталогам типа «C:\.\.\…и так много раз…». Следует обратить внимание, что в Windows имена файлов могут начинаться с точки (cmd.exe → echo 123 > .test
), поэтому имя нужно проверять целиком, а не только его первый символ.
Велика вероятность, что во всем остальном вы сможете разобраться своими силами. В качестве домашнего задания можете попробовать добавить в программу поддержку аргументов, указывающих, на каких именно дисках нужно искать файлы, или с какого каталога следует начать. Также можете попробовать добавить аргумент, задающий строку, которая должна содержаться внутри файла. Тут вам пригодятся процедуры, с которыми мы познакомились в заметке Учимся работать с файлами через Windows API.
Дополнение: Как выяснилось, у приведенного кода есть ряд недостатков. Во-первых, при запуске под Wine длина имени файла может превосходить MAX_PATH. Во-вторых, код не учитывает существование симлинков и junction points. В продакшн коде все это должно учитываться.
Дополнение: Получаем список запущенных процессов на Windows API
Метки: C/C++, WinAPI.
Функция FindFirstFile ищет
каталог файла или подкаталог, название которого
соответствует указанному имени файла.
Чтобы определить
дополнительные атрибуты, которые
используются в поиске, используйте функцию FindFirstFileEx.
Синтаксис
HANDLE FindFirstFile( LPCTSTR lpFileName, // имя файла LPWIN32_FIND_DATA lpFindFileData // буфер данных );
Параметры
lpFileName
[in] Указатель на символьную
строку с нулем в конце, которая определяет
правильный каталог или путь и имя файла,
которое может содержать символы
подстановки (*
и ?).
Если символьная строка заканчивается
символом
подстановки, точкой или именем
каталога, пользователь должен иметь доступ
к корневому каталогу и всем вложенным в
него каталогам на пути.
Windows
NT/2000/XP:
В версии ANSI этой функции, имя
ограничено значением числа символов MAX_PATH.
Чтобы выйти за пределы этого ограничения до длины 32
767 символов,
вызовите Unicode версию этой функции и
присоедините спереди пути
«\\?\«. Подробную информацию см. в
статье Именование файлов.
Windows
95/98/Me: Эта символьная
строка не должна выходить за пределы
количества символов значения MAX_PATH.
lpFindFileData
[out] Указатель на структуру WIN32_FIND_DATA,
которая получает информацию о найденном
файле или вложенном каталоге.
Возвращаемые значения
Если функция завершается
успешно, возвращаемое значение — дескриптор
поиска, используемый в последующем вызове
функции FindNextFile или
FindClose.
Если функция завершается
ошибкой, возвращаемое значение — INVALID_HANDLE_VALUE.
Чтобы получить дополнительные данные об
ошибке, вызовите GetLastError.
Замечания
Функция FindFirstFile открывает дескриптор
поиска и возвращает информацию о первом
файле, имя которого соответствует
указанному образцу. Она ищет и длинные и
короткие имена файла. После того, как
дескриптор поиска был установлен,
функция FindNextFile используется, чтобы искать
другие файлы, которые соответствуют
некоторому шаблону. Когда
дескриптор
поиска — больше не нужен, закройте его,
используя функцию FindClose.
В редких случаях, информация об атрибутах
файла файловой системы NTFS
может быть не текущей, когда Вы вызываете
эту функцию. Чтобы получить текущие
атрибуты файла NTFS, вызовите функцию GetFileInformationByHandle.
Эта функция ищет файлы
только
по имени; она не может использоваться для
поиска на основе атрибута.
Вы не можете использовать корневые
каталоги как вводимую строку в параметре lpFileName
для FindFirstFile, с или без
заключительного обратного слэша (\).
Чтобы проверить файлы в корневом каталоге,
используйте что то подобное «C:\*
» и пройдитесь по всему каталогу
при помощи функции FindNextFile.
Чтобы получить атрибуты корневого каталога,
используйте функцию GetFileAttributes.
Присоединенная спереди символьная строка
«\\?\ » не дает доступ к
корневому каталогу.
Точно так же в сетевом
ресурсе Вы можете использовать для
параметра lpFileName
форму
«\\server\service\*«, но нельзя
использовать lpFileName,
который указывает на ресурс
непосредственно, типа «\\server\service«.
Чтобы исследовать какой-либо
каталог, а не корневой каталог,
используйте соответствующий путь к этому
каталогу без завершающего
обратного слэша (\).
Например, аргумент «C:\windows»
возвратит информацию о каталоге
«C:\windows«, а не о каком-либо
каталоге или файле в «C:\windows«.
Попытка открыть поиск с конечным
обратным слэшем (\)
будет всегда завершаться ошибкой.
Отдавайте себе отчет в том, что кто — то
может создать или удалить этот файл в
промежутке времени, когда Вы сделали запрос
о результатах поиска и когда получили
ответную информацию. Поэтому, если
Вы надумали создать файл, лучше
использовать функцию CreateFile
с CREATE_NEW (сбой,
если файл существует) или OPEN_EXISTING
(сбой, если файл не существует).
Код примера
Нижеследующий код показывает минимальное
использование функции FindFirstFile.
#define _WIN32_WINNT 0x0400 #include "windows.h" #include <stdio.h> int main(int argc, char *argv[]) { WIN32_FIND_DATA FindFileData; HANDLE hFind; printf ("Target file is %s.\n", argv[1]); hFind = FindFirstFile(argv[1], &FindFileData); if (hFind == INVALID_HANDLE_VALUE)
{ printf ("Invalid File Handle. GetLastError reports %d\n",
GetLastError ()); return (0); }
else
{ printf ("The first file found is %s\n", FindFileData.cFileName); FindClose(hFind); return (1); } }
Другой пример, см. в статье Список
файлов в каталоге.
Смотри также
Обзор Управление файлами, Функции,
используемые в управлении файлами,
FindClose,
FindFirstFileEx, FindNextFile, GetFileAttributes, SetFileAttributes,
WIN32_FIND_DATA
Размещение и
|
||
К |
Windows XP |
Да |
л |
Windows 2000 |
Да |
и |
Windows NT |
Да |
е |
Windows Me |
Да |
н |
Windows 98 |
Да |
т |
Windows 95
|
Да |
С |
Windows Server 2003 |
Да |
е | Windows 2000 Server |
Да |
р | Windows NT Server |
Да |
в | ||
е | ||
р | ||
Используемая
|
Kernel32.lib |
|
Используемая DLL |
— | |
Заголовочный файл |
||
— объявлено в
|
Winbase.h |
|
— включено в |
Windows.h |
|
Unicode |
Реализуется как версии Unicode |
|
Замечания по платформе |
Не имеется |
Для поиска файлов используется две функции. Первая функция начинает поиск:
HANDLE FindFirstFile ( LPCTSTR lpFileName, // какой файл ищем можно указывать маску *, ? LPWIN32_FIND_DATA lpFindFileData // указатель на структуру с информацией );
В случае ошибке вернет INVALID_HANDLE_VALUE. Для продолжения поиска используется функция:
BOOL FindNextFile ( HANDLE hFindFile, // указатель на поиск LPWIN32_FIND_DATA lpFindFileData // указатель на структуру с информацией );
А теперь пробуем все вместе:
#include "stdafx.h" #include "windows.h" #include "iostream.h" void main() { WIN32_FIND_DATA FindFileData; HANDLE hf; hf=FindFirstFile("c:\\*", &FindFileData); if (hf!=INVALID_HANDLE_VALUE) { do { cout << FindFileData.cFileName << endl; } while (FindNextFile(hf,&FindFileData)!=0); FindClose(hf); } }
И смотрим. Ага, сработало:
Точно так же Вы можете получить список доступных сетевых ресурсов.
hf=FindFirstFile("\\\\Servers\\work\\*", &FindFileData);
2024-12-03
Введение
В Windows API (WinAPI) существует множество функций для работы с файлами и каталогами. Ниже приведены некоторые из наиболее распространенных файловых операций, которые можно выполнить с использованием WinAPI в языке программирования C/C++.
- Создание файла:
CreateFile
: Эта функция позволяет создавать новые файлы или открывать существующие. Она также позволяет указать параметры доступа, атрибуты и так далее.
- Чтение файла:
ReadFile
: Для чтения данных из файла в буфер.SetFilePointer
иSetFilePointerEx
: Установка указателя файла для чтения с определенной позиции.
- Запись в файл:
WriteFile
: Для записи данных в файл.SetEndOfFile
: Установка размера файла.
- Удаление файла:
DeleteFile
: Для удаления файла.
- Переименование и перемещение файла:
MoveFile
иMoveFileEx
: Переименование или перемещение файла или каталога.
- Работа с атрибутами файла:
GetFileAttributes
иGetFileAttributesEx
: Получение атрибутов файла.SetFileAttributes
: Установка атрибутов файла.
- Проверка существования файла:
FileExists
: Проверка существования файла с использованиемFindFirstFile
иFindNextFile
.
- Работа с каталогами:
CreateDirectory
иCreateDirectoryEx
: Создание каталогов.RemoveDirectory
: Удаление каталогов.
- Получение информации о файле:
GetFileInformationByHandle
: Получение информации о файле, такой как размер, дата создания и т. д.
- Закрытие файла:
CloseHandle
: Закрытие открытого файла или дескриптора каталога.
Пример кода на C/C++ для открытия файла, чтения из него и закрытия файла с использованием WinAPI:
#include <windows.h>
#include "iostream"
int main() {
SetConsoleOutputCP(1251);
// Открыть файл для чтения
HANDLE hFile = CreateFile("example.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
// Чтение данных из файла
char buffer[1024];
DWORD bytesRead;
if (ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL)) {
// Обработка данных
}
// Закрыть файл
CloseHandle(hFile);
} else {
// Обработка ошибки открытия файла
std::cout << "Не удалось открыть файл" << std::endl;
}
return 0;
}
Создание файла
Создание файла в Windows с использованием WinAPI можно выполнить с помощью функции CreateFile
. Вот пример на языке C++, который демонстрирует, как создать новый файл:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
// Открыть или создать файл для записи
HANDLE hFile = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
// Файл успешно создан
std::cout << "Файл '" << fileName << "' успешно создан." << std::endl;
// Закрыть файл
CloseHandle(hFile);
} else {
// Обработать ошибку
DWORD error = GetLastError();
if (error == ERROR_FILE_EXISTS) {
std::cout << "Файл '" << fileName << "' уже существует." << std::endl;
} else {
std::cerr << "Не удалось создать файл '" << fileName << "'. Ошибка " << error << std::endl;
}
}
return 0;
}
В этом примере:
LPCSTR fileName
— это строка, представляющая путь и имя файла. Замените его на желаемый путь и имя файла.CreateFile
используется для создания файла с заданными параметрами. В данном случае, мы используемCREATE_NEW
, чтобы создать новый файл только в том случае, если он не существует.- Если файл успешно создан, мы выводим сообщение об успехе и затем закрываем файл с помощью
CloseHandle
. - Если файл уже существует или возникает другая ошибка, мы выводим соответствующее сообщение.
Функция CreateFile
в Windows API имеет множество параметров, которые позволяют настроить операцию создания или открытия файла подробно. Вот общий вид прототипа функции CreateFile
:
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
Давайте рассмотрим каждый параметр более подробно:
lpFileName
(LPCTSTR):- Этот параметр представляет собой путь к файлу или устройству. Он может быть строкой в формате многобайтовых символов (ANSI) или широких символов (Unicode), в зависимости от того, какой тип используется:
LPCSTR
для ANSI илиLPCWSTR
для Unicode. - Примеры:
- ANSI:
"C:\\example.txt"
- Unicode:
L"C:\\example.txt"
- ANSI:
- Этот параметр представляет собой путь к файлу или устройству. Он может быть строкой в формате многобайтовых символов (ANSI) или широких символов (Unicode), в зависимости от того, какой тип используется:
dwDesiredAccess
(DWORD):- Определяет режим доступа к файлу. Это флаги, которые указывают, какие операции можно выполнять с файлом. Например:
GENERIC_READ
: Разрешает чтение файла.GENERIC_WRITE
: Разрешает запись в файл.
- Вы можете комбинировать флаги с помощью операции побитового ИЛИ (
|
) для указания нескольких прав доступа.
- Определяет режим доступа к файлу. Это флаги, которые указывают, какие операции можно выполнять с файлом. Например:
dwShareMode
(DWORD):- Определяет режим совместного доступа к файлу. Это флаги, указывающие, какие типы доступа можно разрешить другим процессам. Например:
FILE_SHARE_READ
: Разрешает другим процессам читать файл.FILE_SHARE_WRITE
: Разрешает другим процессам записывать в файл.
- Определяет режим совместного доступа к файлу. Это флаги, указывающие, какие типы доступа можно разрешить другим процессам. Например:
lpSecurityAttributes
(LPSECURITY_ATTRIBUTES):- Этот параметр позволяет указать атрибуты безопасности для создаваемого файла. Если вы не хотите задавать специальные атрибуты безопасности, можете передать
NULL
.
- Этот параметр позволяет указать атрибуты безопасности для создаваемого файла. Если вы не хотите задавать специальные атрибуты безопасности, можете передать
dwCreationDisposition
(DWORD):- Определяет, что делать, если файл уже существует или не существует. Некоторые из возможных значений:
CREATE_NEW
: Создать новый файл (ошибка, если файл уже существует).CREATE_ALWAYS
: Создать новый файл или перезаписать существующий.OPEN_EXISTING
: Открыть только существующий файл.OPEN_ALWAYS
: Открыть существующий файл или создать новый, если его нет.
- Определяет, что делать, если файл уже существует или не существует. Некоторые из возможных значений:
dwFlagsAndAttributes
(DWORD):- Этот параметр позволяет указать дополнительные атрибуты файла. Например:
FILE_ATTRIBUTE_NORMAL
: Обычный файл без специальных атрибутов.FILE_ATTRIBUTE_READONLY
: Файл только для чтения.
- Этот параметр позволяет указать дополнительные атрибуты файла. Например:
hTemplateFile
(HANDLE):- Этот параметр представляет собой дескриптор файла-шаблона, который используется для определения атрибутов и флагов создаваемого файла. Обычно передается как
NULL
.
- Этот параметр представляет собой дескриптор файла-шаблона, который используется для определения атрибутов и флагов создаваемого файла. Обычно передается как
После вызова функции CreateFile
, она возвращает дескриптор файла (или специальное значение INVALID_HANDLE_VALUE
в случае ошибки). Этот дескриптор файла используется для дальнейших операций с файлом, таких как чтение, запись и закрытие.
Это основные параметры функции CreateFile
, но WinAPI предоставляет ещё больше опций для более сложных сценариев работы с файлами, такие как сжатие, шифрование и работа с устройствами. Вам следует обращаться к официальной документации Microsoft для получения более подробной информации и примеров использования этой функции: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
Чтение файла
Чтение файла в Windows с использованием WinAPI выполняется с помощью функции ReadFile
. Эта функция позволяет считывать данные из файла в буфер. Вот пример на языке C++, который демонстрирует, как читать данные из файла:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
// Открыть файл для чтения
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
char buffer[1024];
DWORD bytesRead;
if (ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL)) {
// Чтение прошло успешно
if (bytesRead > 0) {
// Вывести прочитанные данные на экран
std::cout << "Прочитано " << bytesRead << " байт: " << buffer << std::endl;
} else {
std::cout << "Файл пуст." << std::endl;
}
} else {
// Обработать ошибку чтения
DWORD error = GetLastError();
std::cerr << "Ошибка чтения файла. Код ошибки: " << error << std::endl;
}
// Закрыть файл
CloseHandle(hFile);
} else {
// Обработать ошибку открытия файла
DWORD error = GetLastError();
std::cerr << "Не удалось открыть файл. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере:
LPCSTR fileName
— это строка, представляющая путь и имя файла. Замените его на желаемый путь и имя файла.- Мы используем
CreateFile
для открытия файла для чтения с флагомGENERIC_READ
. - Затем мы используем
ReadFile
для чтения данных из файла в буферbuffer
. - Если чтение прошло успешно, мы выводим прочитанные данные на экран.
- Если возникла ошибка чтения, мы выводим сообщение об ошибке с кодом ошибки.
- Наконец, мы закрываем файл с помощью
CloseHandle
.
Функция ReadFile
в Windows API используется для чтения данных из файла. Вот её прототип:
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
Давайте подробно рассмотрим каждый из параметров:
hFile
(HANDLE):- Это дескриптор файла, который был получен при открытии файла с помощью функции
CreateFile
. Он указывает на файл, из которого будут читаться данные.
- Это дескриптор файла, который был получен при открытии файла с помощью функции
lpBuffer
(LPVOID):- Это указатель на буфер, в который будут считываться данные из файла. Этот буфер должен быть предварительно выделен, и его размер должен быть не меньше, чем
nNumberOfBytesToRead
, чтобы вместить считанные данные.
- Это указатель на буфер, в который будут считываться данные из файла. Этот буфер должен быть предварительно выделен, и его размер должен быть не меньше, чем
nNumberOfBytesToRead
(DWORD):- Этот параметр указывает количество байт, которые нужно прочитать из файла и поместить в буфер
lpBuffer
.
- Этот параметр указывает количество байт, которые нужно прочитать из файла и поместить в буфер
lpNumberOfBytesRead
(LPDWORD):- Это указатель на переменную, в которую будет записано фактическое количество байт, которые были прочитаны из файла. Эта информация может быть полезной, чтобы узнать, сколько данных было считано.
lpOverlapped
(LPOVERLAPPED):- Этот параметр используется для асинхронного чтения файлов и обычно оставляется равным
NULL
для синхронного чтения. Если вы хотите выполнять асинхронное чтение, вы можете создать структуруOVERLAPPED
и передать указатель на неё.
- Этот параметр используется для асинхронного чтения файлов и обычно оставляется равным
После вызова функции ReadFile
, она возвращает TRUE
, если чтение было успешным, и FALSE
, если произошла ошибка. Если чтение было успешным, данные будут доступны в буфере lpBuffer
, и количество считанных байт будет записано в переменную, на которую указывает lpNumberOfBytesRead
.
Запись в файл
Запись данных в файл в Windows с использованием WinAPI выполняется с помощью функции WriteFile
. Эта функция позволяет записать данные из буфера в файл. Вот её прототип:
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
Давайте подробно рассмотрим каждый из параметров:
hFile
(HANDLE):- Это дескриптор файла, который был получен при открытии файла с помощью функции
CreateFile
. Он указывает на файл, в который будут записываться данные.
- Это дескриптор файла, который был получен при открытии файла с помощью функции
lpBuffer
(LPCVOID):- Это указатель на буфер, из которого будут записываться данные в файл. Этот буфер должен содержать данные, которые вы хотите записать.
nNumberOfBytesToWrite
(DWORD):- Этот параметр указывает количество байт, которые нужно записать в файл из буфера
lpBuffer
.
- Этот параметр указывает количество байт, которые нужно записать в файл из буфера
lpNumberOfBytesWritten
(LPDWORD):- Это указатель на переменную, в которую будет записано фактическое количество байт, которые были успешно записаны в файл. Эта информация может быть полезной, чтобы узнать, сколько данных было записано.
lpOverlapped
(LPOVERLAPPED):- Этот параметр используется для асинхронной записи файлов и обычно оставляется равным
NULL
для синхронной записи. Если вы хотите выполнять асинхронную запись, вы можете создать структуруOVERLAPPED
и передать указатель на неё.
- Этот параметр используется для асинхронной записи файлов и обычно оставляется равным
После вызова функции WriteFile
, она возвращает TRUE
, если запись была успешной, и FALSE
, если произошла ошибка. Если запись была успешной, количество фактически записанных байт будет записано в переменную, на которую указывает lpNumberOfBytesWritten
.
Вот пример использования функции WriteFile
для записи данных в файл:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
// Открыть файл для записи
HANDLE hFile = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
const char *data = "Пример записи в файл.";
DWORD bytesWritten;
if (WriteFile(hFile, data, strlen(data), &bytesWritten, NULL)) {
// Запись прошла успешно
std::cout << "Записано " << bytesWritten << " байт." << std::endl;
} else {
// Обработать ошибку записи
DWORD error = GetLastError();
std::cerr << "Ошибка записи в файл. Код ошибки: " << error << std::endl;
}
// Закрыть файл
CloseHandle(hFile);
} else {
// Обработать ошибку открытия файла
DWORD error = GetLastError();
std::cerr << "Не удалось открыть/создать файл. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере мы открываем файл для записи с помощью CreateFile
, затем используем WriteFile
для записи данных в файл и, наконец, закрываем файл с помощью CloseHandle
. После успешной записи мы выводим количество записанных байт.
Удаление файла
Для удаления файла в Windows с использованием WinAPI вы можете использовать функцию DeleteFile
. Вот её прототип:
BOOL DeleteFile(
LPCTSTR lpFileName
);
Давайте рассмотрим параметр этой функции:
lpFileName
(LPCTSTR):- Этот параметр представляет собой строку, содержащую путь к файлу, который вы хотите удалить. Обычно это Unicode-строка, представленная как
LPCWSTR
для широких символов илиLPCTSTR
для многобайтовых символов.
- Этот параметр представляет собой строку, содержащую путь к файлу, который вы хотите удалить. Обычно это Unicode-строка, представленная как
Пример использования функции DeleteFile
для удаления файла:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
if (DeleteFile(fileName)) {
std::cout << "Файл '" << fileName << "' успешно удалён." << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось удалить файл '" << fileName << "'. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере:
LPCSTR fileName
— это строка, представляющая путь и имя файла, который вы хотите удалить. Замените его на путь и имя вашего файла.- Мы вызываем
DeleteFile
с указанием имени файла для удаления. - Если файл успешно удалён, мы выводим сообщение об успехе.
- Если удаление не удалось, мы выводим сообщение об ошибке с кодом ошибки.
Переименование и перемещение
Для переименования и перемещения файла в Windows с использованием WinAPI, вы можете воспользоваться функцией MoveFile
или её вариациями. Вот примеры использования:
Переименование файла:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR oldFileName = "C:\\путь\\к\\старому\\файлу\\old_file.txt"; // Замените старый путь и имя файла
LPCSTR newFileName = "C:\\путь\\к\\новому\\файлу\\new_file.txt"; // Замените новый путь и имя файла
if (MoveFile(oldFileName, newFileName)) {
std::cout << "Файл успешно переименован в '" << newFileName << "'." << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось переименовать файл. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере:
- Мы используем функцию
MoveFile
для переименования файла или перемещения его в новое место. - Если операция прошла успешно, выводится сообщение об успехе.
- Если операция не удалась, выводится сообщение об ошибке с кодом ошибки.
Работа с атрибутами файла
Вы можете управлять атрибутами файла в Windows с использованием WinAPI с помощью функций GetFileAttributes
и SetFileAttributes
. Вот примеры работы с атрибутами файла:
Получение атрибутов файла:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
DWORD fileAttributes = GetFileAttributes(fileName);
if (fileAttributes != INVALID_FILE_ATTRIBUTES) {
if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
std::cout << "Файл '" << fileName << "' - это каталог." << std::endl;
} else {
std::cout << "Файл '" << fileName << "' - это обычный файл." << std::endl;
}
if (fileAttributes & FILE_ATTRIBUTE_READONLY) {
std::cout << "Файл '" << fileName << "' доступен только для чтения." << std::endl;
}
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось получить атрибуты файла. Код ошибки: " << error << std::endl;
}
return 0;
}
Установка атрибутов файла:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
// Получить текущие атрибуты файла
DWORD fileAttributes = GetFileAttributes(fileName);
if (fileAttributes != INVALID_FILE_ATTRIBUTES) {
// Установить новые атрибуты (например, сделать файл доступным только для чтения)
fileAttributes |= FILE_ATTRIBUTE_READONLY;
if (SetFileAttributes(fileName, fileAttributes)) {
std::cout << "Атрибуты файла '" << fileName << "' успешно изменены." << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось изменить атрибуты файла. Код ошибки: " << error << std::endl;
}
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось получить атрибуты файла. Код ошибки: " << error << std::endl;
}
return 0;
}
В обоих примерах:
- Мы используем функцию
GetFileAttributes
, чтобы получить текущие атрибуты файла. - Затем мы можем изменить атрибуты файла, если это необходимо, например, сделать файл доступным только для чтения с помощью бита
FILE_ATTRIBUTE_READONLY
. - Для изменения атрибутов файла мы используем функцию
SetFileAttributes
.
Помните, что некоторые атрибуты, такие как FILE_ATTRIBUTE_SYSTEM
, могут быть изменены только с административными правами. Убедитесь, что ваше приложение имеет соответствующие права доступа к файлу перед изменением его атрибутов.
Проверка существования файла
Для проверки существования файла в Windows с использованием WinAPI вы можете воспользоваться функцией PathFileExists
из библиотеки Shlwapi.h или функцией GetFileAttributes
и проверкой возвращаемого значения. Вот примеры:
Используя PathFileExists
:
Для компиляции примера в Code::Blocks нужно подключить библиотеку в настройках компилятора:
-
Project -> Build options -> Linker settings -> Add
-
Добавить “shlwapi”.
#include <windows.h>
#include <Shlwapi.h> // Для PathFileExists
int main() {
SetConsoleOutputCP(1251);
PCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
if (PathFileExists(fileName)) {
// Файл существует
printf("Файл '%s' существует.\n", fileName);
} else {
// Файл не существует
printf("Файл '%s' не существует.\n", fileName);
}
return 0;
}
Используя GetFileAttributes
:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
DWORD fileAttributes = GetFileAttributes(fileName);
if (fileAttributes != INVALID_FILE_ATTRIBUTES && !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
// Файл существует
std::cout << "Файл '" << fileName << "' существует." << std::endl;
} else {
// Файл не существует или это каталог
std::cout << "Файл '" << fileName << "' не существует или это каталог." << std::endl;
}
return 0;
}
Оба примера позволяют вам проверить существование файла. Первый пример использует функцию PathFileExists
, которая является более простой и интуитивно понятной для этой задачи. Второй пример использует GetFileAttributes
и проверяет атрибуты файла, чтобы определить его существование. Вы можете выбрать подходящий для вас метод.
Поиск файлов
Для поиска файлов в Windows с использованием WinAPI, вы можете воспользоваться функцией FindFirstFile
и её итеративной версией FindNextFile
. Эти функции позволяют вам искать файлы по определенным критериям в указанном каталоге. Вот пример поиска файлов:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR searchPath = "C:\\путь\\к\\каталогу\\*.*"; // Замените путь к каталогу по вашему усмотрению
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile(searchPath, &findFileData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
// Элемент найден, и это не каталог
std::cout << "Имя файла: " << findFileData.cFileName << std::endl;
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind); // Закрыть дескриптор поиска
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось выполнить поиск файлов. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере:
-
Мы указываем путь к каталогу и шаблон имени файлов в
searchPath
. Например,"C:\\путь\\к\\каталогу\\*.*"
будет искать все файлы в указанном каталоге. -
Мы используем
FindFirstFile
для начала поиска файлов. Функция возвращает дескриптор поиска (типаHANDLE
). -
Затем мы используем цикл
do-while
сFindNextFile
для итеративного поиска следующих файлов в каталоге. ФункцияFindNextFile
возвращает0
, когда больше файлов для поиска нет. -
В цикле мы проверяем атрибуты найденных элементов, и если элемент не является каталогом (
FILE_ATTRIBUTE_DIRECTORY
не установлен), то выводим имя файла. -
Наконец, мы закрываем дескриптор поиска с помощью
FindClose
.
Помните, что при использовании FindFirstFile
и FindNextFile
нужно следить за максимальной длиной пути и имени файла, чтобы избежать переполнения буфера. Если вам нужно выполнить более сложные запросы поиска, вы можете использовать FindFirstFileEx
.
Работа с каталогами
Для работы с каталогами в Windows с использованием WinAPI вы можете использовать функции, такие как CreateDirectory
, RemoveDirectory
, SetCurrentDirectory
, и GetCurrentDirectory
. Вот примеры работы с каталогами:
Создание каталога:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR directoryName = "C:\\путь\\к\\новому\\каталогу"; // Замените путь и имя каталога по вашему усмотрению
if (CreateDirectory(directoryName, NULL)) {
std::cout << "Каталог '" << directoryName << "' успешно создан." << std::endl;
} else {
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS) {
std::cerr << "Каталог '" << directoryName << "' уже существует." << std::endl;
} else {
std::cerr << "Не удалось создать каталог. Код ошибки: " << error << std::endl;
}
}
return 0;
}
Удаление каталога:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR directoryName = "C:\\путь\\к\\каталогу\\для_удаления"; // Замените путь и имя каталога по вашему усмотрению
if (RemoveDirectory(directoryName)) {
std::cout << "Каталог '" << directoryName << "' успешно удалён." << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось удалить каталог. Код ошибки: " << error << std::endl;
}
return 0;
}
Установка текущего каталога:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR newDirectory = "C:\\путь\\к\\новому\\каталогу"; // Замените путь и имя каталога по вашему усмотрению
if (SetCurrentDirectory(newDirectory)) {
std::cout << "Текущий каталог установлен в '" << newDirectory << "'." << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось установить текущий каталог. Код ошибки: " << error << std::endl;
}
return 0;
}
Получение текущего каталога:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
CHAR currentDirectory[MAX_PATH];
if (GetCurrentDirectory(MAX_PATH, currentDirectory) != 0) {
std::cout << "Текущий каталог: " << currentDirectory << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось получить текущий каталог. Код ошибки: " << error << std::endl;
}
return 0;
}
Функции CreateDirectory
и RemoveDirectory
могут возвращать ошибку ERROR_ALREADY_EXISTS
, если каталог уже существует.
Получение информации о файле
Функция GetFileInformationByHandle
предоставляет информацию о файле на основе его дескриптора. Эта функция предоставляет подробные сведения о файле, такие как размер, атрибуты, времена создания и др. Вот пример использования функции GetFileInformationByHandle
:
#include <windows.h>
#include <iostream>
#include <ctime>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
// Открыть файл для получения дескриптора
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
BY_HANDLE_FILE_INFORMATION fileInfo;
if (GetFileInformationByHandle(hFile, &fileInfo)) {
std::cout << "Имя файла: " << fileName << std::endl;
std::cout << "Размер файла: " << fileInfo.nFileSizeLow << " байт" << std::endl;
std::cout << "Атрибуты файла: " << fileInfo.dwFileAttributes << std::endl;
SYSTEMTIME sysTime;
FileTimeToSystemTime(&fileInfo.ftCreationTime, &sysTime);
std::cout << "Дата создания: " << sysTime.wDay << "." << sysTime.wMonth << "." << sysTime.wYear
<< " " << sysTime.wHour << ":" << sysTime.wMinute << ":" << sysTime.wSecond << std::endl;
FileTimeToSystemTime(&fileInfo.ftLastAccessTime, &sysTime);
std::cout << "Последний доступ: " << sysTime.wDay << "." << sysTime.wMonth << "." << sysTime.wYear
<< " " << sysTime.wHour << ":" << sysTime.wMinute << ":" << sysTime.wSecond << std::endl;
FileTimeToSystemTime(&fileInfo.ftLastWriteTime, &sysTime);
std::cout << "Последнее изменение: " << sysTime.wDay << "." << sysTime.wMonth << "."
<< sysTime.wYear << " " << sysTime.wHour << ":" << sysTime.wMinute << ":" << sysTime.wSecond << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось получить информацию о файле. Код ошибки: " << error << std::endl;
}
// Закрыть дескриптор файла
CloseHandle(hFile);
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось открыть файл. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере:
-
Мы открываем файл с помощью функции
CreateFile
, чтобы получить дескриптор файла (hFile
). -
Затем мы используем
GetFileInformationByHandle
, передавая ей дескриптор файла и указатель на структуруBY_HANDLE_FILE_INFORMATION
, в которую будет записана информация о файле. -
Мы выводим полученную информацию о файле, такую как имя, размер, атрибуты и времена.
-
После использования дескриптора файла мы его закрываем с помощью
CloseHandle
.
Обратите внимание, что GetFileInformationByHandle
предоставляет более полную информацию о файле, чем GetFileAttributes
или GetFileAttributesEx
.
Закрытие файла
Для закрытия файла в Windows с использованием WinAPI, вы можете использовать функцию CloseHandle
, передав в неё дескриптор файла, который был получен при его открытии с помощью функции CreateFile
или других функций, возвращающих дескриптор файла. Вот пример закрытия файла:
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(1251);
LPCSTR fileName = "C:\\путь\\к\\вашему\\файлу\\example.txt"; // Замените путь и имя файла по вашему усмотрению
// Открыть файл для чтения
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
// Выполняйте операции с файлом
// Закрыть дескриптор файла
CloseHandle(hFile);
std::cout << "Файл закрыт." << std::endl;
} else {
DWORD error = GetLastError();
std::cerr << "Не удалось открыть файл. Код ошибки: " << error << std::endl;
}
return 0;
}
В этом примере:
-
Мы открываем файл с помощью функции
CreateFile
, чтобы получить дескриптор файла (hFile
). -
Затем выполняем операции с файлом, если это необходимо.
-
После завершения работы с файлом мы закрываем дескриптор файла с помощью функции
CloseHandle
.
Закрытие дескриптора файла важно, чтобы освободить ресурсы и предотвратить утечку дескрипторов. Вы должны закрывать дескрипторы файлов после их использования.
Работа с различными системными объектами
Функция CreateFile
в Windows может работать с различными типами объектов, такими как файлы, устройства, каталоги и т. д. Вот некоторые из типов объектов, с которыми CreateFile
может работать:
-
Файлы: Это наиболее распространенный тип объектов. Вы можете открывать и создавать обычные файлы разных форматов, такие как текстовые, бинарные, конфигурационные и т. д.
-
Устройства: Функция
CreateFile
может быть использована для работы с системными устройствами, такими как диски, порты COM, принтеры, звуковые устройства и другие. Для этого необходимо указать путь к устройству, например,\\.\COM1
для открытия COM1 порта. -
Каталоги: С помощью
CreateFile
можно открывать каталоги и выполнять операции с их содержимым, такие как чтение и запись файлов внутри каталога. -
Специальные объекты: Это может включать объекты, такие как метки томов, события, мьютексы, семафоры и другие системные ресурсы. Для доступа к ним также используется
CreateFile
. -
Пайпы (каналы): Функция
CreateFile
может использоваться для открытия и взаимодействия с именованными и анонимными каналами, которые предоставляют механизмы межпроцессного взаимодействия (IPC). -
Mailslots: Mailslots — это еще один механизм IPC, и
CreateFile
может использоваться для создания или открытия именованных mailslots для передачи сообщений между процессами. -
Реестр: С помощью
CreateFile
можно работать с реестром Windows, например, открывать ключи реестра и выполнять операции с данными в них. -
Потоки ввода-вывода (I/O streams):
CreateFile
может быть использован для создания и открытия потоков ввода-вывода для работы с консольным вводом-выводом.
Важно отметить, что для каждого типа объекта существуют разные флаги и параметры, которые нужно указать при вызове CreateFile
, чтобы правильно работать с этими объектами. Кроме того, различные типы объектов могут подразумевать разные операции ввода-вывода и методы взаимодействия.
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
//--------------------------------------------------------------------------- #include <windows.h> #include <stdio.h> #include <conio.h> #pragma hdrstop #define BUF_SIZE 256 #define ARR_SIZE 256 #define DUF_SIZE 256 //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { int cchCurDir=250; char lpszCurDir; //currentDIrectory char Catalog_name[250]; GetCurrentDirectory(cchCurDir, Catalog_name); MessageBox (NULL,Catalog_name,"Текущий каталог",MB_OK); //Katalog v kotorom ishem CHAR first_catalog[500]; printf( "\nVvedite katalog dlia poiska:\n "); scanf("%s",first_catalog); if (!SetCurrentDirectory(first_catalog)) { MessageBox (NULL,"Скорее всего папки, в которой вы хотите осуществить поиск не существует!","Ошибка",MB_OK); } //MASKA POISKA char NewDir[MAX_PATH]; int raz; SYSTEMTIME d; HANDLE b; FILETIME e; WIN32_FIND_DATA a; //Поиск первого файла printf("\nVvedite masku poiska:\n"); scanf("%s",NewDir) ; b=FindFirstFile(NewDir, &a); if(! (b ==INVALID_HANDLE_VALUE)) { FileTimeToLocalFileTime(&a.ftCreationTime, &e ); FileTimeToSystemTime(&e,&d); printf("\n%s ==== %i.%i.%i %i:%i:%i Size:%i",a.cFileName,d.wDay,d.wMonth,d.wYear,d.wHour,d.wMinute,d.wSecond,a.nFileSizeLow); } //Поиск остальных файлов по маске и raz = a.nFileSizeLow; strcpy(NewDir, a.cFileName); while (FindNextFile(b, &a)==TRUE) { FileTimeToLocalFileTime(&a.ftCreationTime, &e ); FileTimeToSystemTime(&e,&d); printf("\n%s ==== %i.%i.%i %i:%i:%i Size:%i",a.cFileName,d.wDay,d.wMonth,d.wYear,d.wHour,d.wMinute,d.wSecond,a.nFileSizeLow); if (a.nFileSizeLow>raz) { raz = a.nFileSizeLow; strcpy(NewDir, a.cFileName); } } printf("\n"); printf( "Name of maxSize file - %s", NewDir); getch(); return 0; } //--------------------------------------------------------------------------- |