一、Windows文件系统概述
1.1 Windows支持的文件系统
cpp
NTFS(NT File System) - 现代Windows默认,支持ACL、加密、压缩
FAT32(File Allocation Table) - 兼容性好,最大4GB文件
exFAT(Extended FAT) - 大文件支持,适合闪存设备
ReFS(Resilient File System) - 服务器级,数据完整性
1.2 文件路径格式
cpp
// 不同路径表示
"file.txt" // 当前目录
".\\data\\file.txt" // 相对路径
"C:\\Windows\\system32" // 绝对路径(驱动器路径)
"\\\\Server\\Share\\file" // UNC路径(网络共享)
"\\\\.\\PhysicalDrive0" // 设备名称空间路径
"\\\\?\\C:\\verylongpath" // 扩展长度路径(超过MAX_PATH)
1.3 Windows文件API分类
-
传统Win32 API:CreateFile, ReadFile, WriteFile等
-
CRT(C运行时)函数:fopen, fread, fwrite(最终调用Win32 API)
-
COM接口:IFileOperation(Shell操作)
-
.NET Framework :System.IO命名空间
-
现代Windows API:Windows.Storage(UWP应用)
二、核心文件操作函数
2.1 文件创建与打开 - CreateFile
函数原型
cpp
HANDLE CreateFile(
LPCSTR lpFileName, // 文件名
DWORD dwDesiredAccess, // 访问权限
DWORD dwShareMode, // 共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性
DWORD dwCreationDisposition, // 创建方式
DWORD dwFlagsAndAttributes, // 文件属性/标志
HANDLE hTemplateFile // 模板文件句柄
);
参数详解
1. dwDesiredAccess(访问权限)
cpp
// 基本访问权限
0 // 仅查询属性(无数据访问)
GENERIC_READ // 读访问
GENERIC_WRITE // 写访问
GENERIC_EXECUTE // 执行访问
GENERIC_READ | GENERIC_WRITE // 读写访问
// 标准访问权限(更精细控制)
FILE_READ_DATA // 读取文件数据
FILE_WRITE_DATA // 写入文件数据
FILE_APPEND_DATA // 追加数据
FILE_READ_EA // 读取扩展属性
FILE_WRITE_EA // 写入扩展属性
FILE_EXECUTE // 执行文件
FILE_READ_ATTRIBUTES // 读取文件属性
FILE_WRITE_ATTRIBUTES // 写入文件属性
// 标准权限组合
STANDARD_RIGHTS_REQUIRED // 删除/读取安全描述符/更改权限等
STANDARD_RIGHTS_READ // 读取权限
STANDARD_RIGHTS_WRITE // 写入权限
2. dwShareMode(共享模式)
cpp
0 // 独占访问,其他进程无法打开
FILE_SHARE_READ // 允许其他进程读
FILE_SHARE_WRITE // 允许其他进程写
FILE_SHARE_DELETE // 允许其他进程删除
// 常见组合
FILE_SHARE_READ | FILE_SHARE_WRITE // 允许多进程读写
3. dwCreationDisposition(创建方式)
cpp
CREATE_NEW // 创建新文件,如果存在则失败
CREATE_ALWAYS // 总是创建,覆盖已存在文件
OPEN_EXISTING // 打开已存在文件,不存在则失败
OPEN_ALWAYS // 打开文件,不存在则创建
TRUNCATE_EXISTING // 打开并清空文件,不存在则失败
使用示例
cpp
#include <windows.h>
#include <stdio.h>
void CreateFileExamples() {
HANDLE hFile;
// 示例1:创建新文件(读写)
hFile = CreateFile(
L"test.txt", // 文件名
GENERIC_READ | GENERIC_WRITE, // 读写权限
0, // 独占访问
NULL, // 默认安全属性
CREATE_NEW, // 创建新文件
FILE_ATTRIBUTE_NORMAL, // 普通文件
NULL // 无模板
);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
if (err == ERROR_FILE_EXISTS) {
printf("文件已存在!\n");
}
} else {
printf("文件创建成功!\n");
CloseHandle(hFile);
}
// 示例2:打开现有文件(只读)
hFile = CreateFile(
L"test.txt",
GENERIC_READ,
FILE_SHARE_READ, // 允许其他进程读
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
printf("文件打开成功!\n");
CloseHandle(hFile);
}
// 示例3:异步文件操作
hFile = CreateFile(
L"largefile.dat",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
}
2.2 文件读取 - ReadFile
函数原型
cpp
BOOL ReadFile(
HANDLE hFile, // 文件句柄
LPVOID lpBuffer, // 数据缓冲区
DWORD nNumberOfBytesToRead, // 要读取的字节数
LPDWORD lpNumberOfBytesRead, // 实际读取的字节数
LPOVERLAPPED lpOverlapped // 重叠I/O结构指针
);
2.3 文件写入 - WriteFile
函数原型
cpp
BOOL WriteFile(
HANDLE hFile, // 文件句柄
LPCVOID lpBuffer, // 数据缓冲区
DWORD nNumberOfBytesToWrite, // 要写入的字节数
LPDWORD lpNumberOfBytesWritten, // 实际写入的字节数
LPOVERLAPPED lpOverlapped // 重叠I/O结构指针
);
2.4 文件指针操作
2.4.1 SetFilePointer - 移动文件指针
cpp
DWORD SetFilePointer(
HANDLE hFile, // 文件句柄
LONG lDistanceToMove, // 移动距离(低32位)
PLONG lpDistanceToMoveHigh, // 移动距离(高32位)
DWORD dwMoveMethod // 移动基准
);
// 移动基准常量
FILE_BEGIN // 从文件开头
FILE_CURRENT // 从当前位置
FILE_END // 从文件结尾
2.4.2 SetFilePointerEx - 扩展版本(推荐)
cpp
BOOL SetFilePointerEx(
HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer,
DWORD dwMoveMethod
);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
hFile |
HANDLE |
已打开的文件句柄,需具有 GENERIC_READ或 GENERIC_WRITE权限 |
liDistanceToMove |
LARGE_INTEGER |
要移动的距离(有符号 64 位整数),正数向文件尾方向移动,负数向文件头方向移动 |
lpNewFilePointer |
PLARGE_INTEGER |
可选参数,用于接收移动后的新文件指针位置。如果为 NULL,则不返回 |
dwMoveMethod |
DWORD |
移动的基准位置,取值如下: • FILE_BEGIN(0):从文件头开始 • FILE_CURRENT(1):从当前位置开始 • FILE_END(2):从文件尾开始 |
返回值
-
成功:返回
TRUE,此时lpNewFilePointer会包含新位置。 -
失败:返回
FALSE,可调用GetLastError()获取错误码。
示例:
cpp
HANDLE hFile = CreateFile("example.txt", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
LARGE_INTEGER liPos = {0};
liPos.QuadPart = 1024; // 移动到第1024字节处
LARGE_INTEGER newPos = {0};
if (SetFilePointerEx(hFile, liPos, &newPos, FILE_BEGIN)) {
printf("新位置: %lld\n", newPos.QuadPart);
} else {
printf("错误: %d\n", GetLastError());
}
CloseHandle(hFile);
}
2.4.3 GetFileSize - 获取文件大小
cpp
DWORD GetFileSize(
HANDLE hFile, // 文件句柄
LPDWORD lpFileSizeHigh // 文件大小高32位
);
// 替代函数(推荐)
BOOL GetFileSizeEx(
HANDLE hFile, // 文件句柄
PLARGE_INTEGER lpFileSize // 文件大小
);
示例:
cpp
// 方法1:GetFileSize
HANDLE hFile = CreateFile(...);
DWORD fileSizeHigh = 0;
DWORD fileSizeLow = GetFileSize(hFile, &fileSizeHigh);
if (fileSizeLow == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
printf("获取文件大小失败!\n");
} else {
LONGLONG totalSize = ((LONGLONG)fileSizeHigh << 32) | fileSizeLow;
printf("文件大小: %lld 字节\n", totalSize);
}
// 方法2:GetFileSizeEx(更简单)
LARGE_INTEGER fileSize;
if (GetFileSizeEx(hFile, &fileSize)) {
printf("文件大小: %lld 字节\n", fileSize.QuadPart);
}
2.5 文件时间操作
2.5.1 GetFileTime - 获取文件时间
cpp
BOOL GetFileTime(
HANDLE hFile, // 文件句柄
LPFILETIME lpCreationTime, // 创建时间
LPFILETIME lpLastAccessTime, // 最后访问时间
LPFILETIME lpLastWriteTime // 最后修改时间
);
2.5.2 SetFileTime - 设置文件时间
cpp
BOOL SetFileTime(
HANDLE hFile, // 文件句柄
const FILETIME *lpCreationTime, // 创建时间
const FILETIME *lpFileLastAccessTime, // 最后访问时间
const FILETIME *lpLastWriteTime // 最后修改时间
);
时间操作示例:
cpp
#include <windows.h>
#include <stdio.h>
void FileTimeExample(LPCWSTR filename) {
HANDLE hFile = CreateFile(
filename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) return;
// 获取文件时间
FILETIME ftCreate, ftAccess, ftWrite;
if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) {
// 转换FILETIME为SYSTEMTIME(可读格式)
SYSTEMTIME stCreate, stAccess, stWrite;
SYSTEMTIME stLocal;
FileTimeToSystemTime(&ftCreate, &stCreate);
FileTimeToSystemTime(&ftAccess, &stAccess);
FileTimeToSystemTime(&ftWrite, &stWrite);
// 转换为本地时间
FileTimeToLocalFileTime(&ftWrite, &ftWrite);
FileTimeToSystemTime(&ftWrite, &stLocal);
printf("创建时间: %04d-%02d-%02d %02d:%02d:%02d\n",
stCreate.wYear, stCreate.wMonth, stCreate.wDay,
stCreate.wHour, stCreate.wMinute, stCreate.wSecond);
printf("最后修改: %04d-%02d-%02d %02d:%02d:%02d\n",
stLocal.wYear, stLocal.wMonth, stLocal.wDay,
stLocal.wHour, stLocal.wMinute, stLocal.wSecond);
}
// 设置新的修改时间(当前时间)
SYSTEMTIME stNew;
GetSystemTime(&stNew); // 获取当前UTC时间
FILETIME ftNew;
SystemTimeToFileTime(&stNew, &ftNew);
// 只更新最后修改时间
SetFileTime(hFile, NULL, NULL, &ftNew);
CloseHandle(hFile);
}