Windows学习笔记-16(Windows文件操作相关)

一、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分类

  1. 传统Win32 API:CreateFile, ReadFile, WriteFile等

  2. CRT(C运行时)函数:fopen, fread, fwrite(最终调用Win32 API)

  3. COM接口:IFileOperation(Shell操作)

  4. .NET FrameworkSystem.IO命名空间

  5. 现代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_READGENERIC_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);
}
相关推荐
齐生15 小时前
iOS 知识点 - IAP 是怎样的?
笔记
tingshuo291718 小时前
D006 【模板】并查集
笔记
tingshuo29172 天前
S001 【模板】从前缀函数到KMP应用 字符串匹配 字符串周期
笔记
阿白的白日梦2 天前
winget基础管理---更新/修改源为国内源
windows
埃博拉酱6 天前
VS Code Remote SSH 连接 Windows 服务器卡在"下载 VS Code 服务器":prcdn DNS 解析失败的诊断与 BITS 断点续传
windows·ssh·visual studio code
唐宋元明清21887 天前
.NET 本地Db数据库-技术方案选型
windows·c#
西岸行者7 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
加号37 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
tryCbest7 天前
Windows环境下配置pip镜像源
windows·pip
呉師傅7 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑