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);
}
相关推荐
时代的凡人10 小时前
0208晨间笔记
笔记
今天只学一颗糖10 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
testpassportcn11 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
游乐码13 小时前
c#变长关键字和参数默认值
学习·c#
x***r15114 小时前
SuperScan4单文件扫描安装步骤详解(附端口扫描与主机存活检测教程)
windows
饭碗、碗碗香14 小时前
【Python学习笔记】:Python的hashlib算法简明指南:选型、场景与示例
笔记·python·学习
Wils0nEdwards15 小时前
初中化学1
笔记
不爱学习的老登15 小时前
Windows客户端与Linux服务器配置ssh无密码登录
linux·服务器·windows
魔力军15 小时前
Rust学习Day4: 所有权、引用和切片介绍
开发语言·学习·rust
wubba lubba dub dub75015 小时前
第三十六周 学习周报
学习