1、课程目标
- 掌握Windows文件操作API
- 理解文件属性和安全描述符
- 学会目录遍历和管理
- 掌握文件映射技术
2、名词解释
| 术语 |
英文 |
说明 |
| 句柄 |
Handle |
内核对象的引用标识 |
| 文件映射 |
File Mapping |
将文件映射到内存 |
| 重叠I/O |
Overlapped I/O |
异步文件操作 |
3、使用工具
| 工具 |
用途 |
| Process Monitor |
监控文件操作 |
| WinObj |
查看内核对象 |
4、技术原理
4.1、文件操作流程
CreateFile -> ReadFile/WriteFile -> CloseHandle
4.2、访问模式
| 标志 |
说明 |
| GENERIC_READ |
读取权限 |
| GENERIC_WRITE |
写入权限 |
| FILE_SHARE_READ |
允许其他进程读取 |
| CREATE_NEW |
创建新文件 |
| OPEN_EXISTING |
打开已存在文件 |
5、代码实现
5.1、示例1:基本文件操作
#include <windows.h>
#include <stdio.h>
void FileOperations() {
// 创建/打开文件
HANDLE hFile = CreateFile(
TEXT("test.txt"),
GENERIC_READ | GENERIC_WRITE,
0, // 不共享
NULL, // 默认安全属性
CREATE_ALWAYS, // 总是创建
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Error: %d\n", GetLastError());
return;
}
// 写入数据
const char* data = "Hello, File API!";
DWORD written;
WriteFile(hFile, data, strlen(data), &written, NULL);
// 移动文件指针到开头
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
// 读取数据
char buffer[256] = {0};
DWORD read;
ReadFile(hFile, buffer, sizeof(buffer)-1, &read, NULL);
printf("Read: %s\n", buffer);
// 获取文件大小
DWORD fileSize = GetFileSize(hFile, NULL);
printf("File size: %d bytes\n", fileSize);
CloseHandle(hFile);
}
5.2、示例2:目录遍历
#include <windows.h>
#include <stdio.h>
void ListDirectory(const TCHAR* path) {
TCHAR searchPath[MAX_PATH];
wsprintf(searchPath, TEXT("%s\\*"), path);
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(searchPath, &fd);
if (hFind == INVALID_HANDLE_VALUE) {
printf("Error: %d\n", GetLastError());
return;
}
do {
// 跳过 . 和 ..
if (lstrcmp(fd.cFileName, TEXT(".")) == 0 ||
lstrcmp(fd.cFileName, TEXT("..")) == 0) {
continue;
}
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
printf("[DIR] %ls\n", fd.cFileName);
// 递归遍历子目录
TCHAR subPath[MAX_PATH];
wsprintf(subPath, TEXT("%s\\%s"), path, fd.cFileName);
ListDirectory(subPath);
} else {
printf("[FILE] %ls (%d bytes)\n",
fd.cFileName, fd.nFileSizeLow);
}
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
}
5.3、示例3:文件映射
#include <windows.h>
#include <stdio.h>
void FileMapping(const TCHAR* filename) {
// 打开文件
HANDLE hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return;
// 创建文件映射对象
HANDLE hMapping = CreateFileMapping(
hFile,
NULL, // 安全属性
PAGE_READWRITE, // 访问模式
0, 0, // 映射大小(0=整个文件)
NULL // 名称
);
if (hMapping == NULL) {
CloseHandle(hFile);
return;
}
// 映射视图到内存
LPVOID pView = MapViewOfFile(
hMapping,
FILE_MAP_ALL_ACCESS,
0, 0, // 偏移
0 // 大小(0=全部)
);
if (pView) {
// 直接操作内存即修改文件
char* data = (char*)pView;
printf("First 32 bytes: %.32s\n", data);
// 修改数据
memcpy(data, "Modified!", 9);
// 刷新到磁盘
FlushViewOfFile(pView, 0);
UnmapViewOfFile(pView);
}
CloseHandle(hMapping);
CloseHandle(hFile);
}
5.4、示例4:文件属性操作
#include <windows.h>
#include <stdio.h>
void FileAttributes(const TCHAR* filename) {
// 获取属性
DWORD attrs = GetFileAttributes(filename);
if (attrs == INVALID_FILE_ATTRIBUTES) {
printf("Error: %d\n", GetLastError());
return;
}
printf("Attributes:\n");
if (attrs & FILE_ATTRIBUTE_READONLY) printf(" Read-only\n");
if (attrs & FILE_ATTRIBUTE_HIDDEN) printf(" Hidden\n");
if (attrs & FILE_ATTRIBUTE_SYSTEM) printf(" System\n");
if (attrs & FILE_ATTRIBUTE_DIRECTORY) printf(" Directory\n");
// 设置隐藏属性
SetFileAttributes(filename, attrs | FILE_ATTRIBUTE_HIDDEN);
// 获取详细信息
WIN32_FILE_ATTRIBUTE_DATA fad;
GetFileAttributesEx(filename, GetFileExInfoStandard, &fad);
printf("Size: %lld\n",
((LONGLONG)fad.nFileSizeHigh << 32) | fad.nFileSizeLow);
}
6、课后作业
- 基础练习:实现文件复制函数
- 目录遍历:递归统计目录大小
- 文件映射:实现大文件的快速搜索
- 文件监控:使用ReadDirectoryChangesW监控目录变化