Windows API函数之文件类函数(一)

三. API之文件处理函数


3.1 函数名:CloseHandle

(1)函数的概述
CloseHandle是一个Windows API函数,用于关闭一个打开的句柄。句柄是Windows中用于标识各种资源(如文件、设备、内存映射等)的抽象标识符。CloseHandle函数会释放与句柄相关联的系统资源,并使得句柄无效。

(2)函数所在的动态链接库
CloseHandle函数位于Windows系统的Kernel32.dll动态链接库中。

(3)函数的原型

BOOL CloseHandle(  
  HANDLE hObject  
);


(4)各参数及返回值的详细解释

  • HANDLE hObject:要关闭的句柄。这个句柄必须是由某个系统函数(如CreateFile、CreateProcess等)返回的有效句柄。
  • 返回值:如果函数成功,返回值为非零。如果函数失败,返回值为零。要获取更详细的错误信息,可以调用GetLastError函数。

(5)函数的详细作用
CloseHandle函数的主要作用是关闭由其他系统函数创建的句柄,并释放与之相关联的系统资源。一旦句柄被关闭,就不能再使用它进行任何操作,否则可能会导致不可预测的行为。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 假设我们使用CreateFile函数创建了一个文件句柄  
    HANDLE hFile = CreateFile(  
        "example.txt",           // 文件名  
        GENERIC_READ,            // 访问模式(只读)  
        0,                       // 共享模式  
        NULL,                    // 安全描述符  
        OPEN_EXISTING,           // 创建/打开模式  
        FILE_ATTRIBUTE_NORMAL,   // 文件属性  
        NULL                     // 模板句柄  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    // ... 使用hFile进行文件操作 ...  
  
    // 关闭句柄  
    if (!CloseHandle(hFile)) {  
        std::cerr << "CloseHandle failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    return 0;  
}


(7)使用时的注意事项

  1. 不要在句柄关闭后再次使用它。这可能会导致不可预测的行为,甚至可能使程序崩溃。
  2. 在多线程环境中,要确保对句柄的访问是同步的,以防止多个线程同时关闭同一个句柄。
  3. 如果CloseHandle函数失败,并返回FALSE,请调用GetLastError函数来获取更详细的错误信息。
  4. 在调用CloseHandle之前,请确保没有其他的API函数正在使用该句柄。例如,如果你使用了一个句柄来读取文件,那么在调用CloseHandle之前,必须确保已经关闭了与该句柄相关联的文件流。

3.2 函数名:CompareFileTime

(1)函数的概述
CompareFileTime 是一个 Windows API 函数,它用于比较两个 FILETIME 结构体表示的文件时间。FILETIME 结构体通常用于表示文件或目录的创建、修改和访问时间。CompareFileTime 函数可以判断两个 FILETIME 结构体中的时间哪个更早、哪个更晚,或者它们是否相同。

(2)函数所在的动态链接库
CompareFileTime 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

LONG CompareFileTime(  
  const FILETIME *lpFileTime1,  
  const FILETIME *lpFileTime2  
);


(4)各参数及返回值的详细解释

  • lpFileTime1:指向第一个 FILETIME 结构体的指针,该结构体包含要比较的时间。
  • lpFileTime2:指向第二个 FILETIME 结构体的指针,该结构体包含要比较的时间。
  • 返回值是一个 LONG 类型的值,表示两个时间的比较结果:如果返回值小于 0,则 lpFileTime1 指向的时间早于 lpFileTime2 指向的时间。如果返回值等于 0,则两个时间相同。如果返回值大于 0,则 lpFileTime1 指向的时间晚于 lpFileTime2 指向的时间。

(5)函数的详细作用
CompareFileTime 函数的作用是比较两个 FILETIME 结构体所表示的时间戳,以确定哪个时间更早、哪个时间更晚,或者它们是否相同。这在进行文件时间比较、时间戳排序等操作时非常有用。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    FILETIME ft1, ft2;  
    // 假设这里已经为 ft1 和 ft2 赋了值,或者从某个文件获取了它们的值  
  
    // 示例:手动设置 FILETIME 值(通常你会从系统或文件获取)  
    // SYSTEMTIME st = { 2023, 1, 1, 0, 0, 0, 0, 0 }; // 示例日期  
    // FileTimeToSystemTime(&ft1, &st); // 这里假设已经实现了这个转换函数  
  
    LONG result = CompareFileTime(&ft1, &ft2);  
  
    if (result < 0) {  
        std::cout << "ft1 is earlier than ft2" << std::endl;  
    } else if (result > 0) {  
        std::cout << "ft1 is later than ft2" << std::endl;  
    } else {  
        std::cout << "ft1 and ft2 are the same" << std::endl;  
    }  
  
    return 0;  
}  


// 注意:上面的代码只是一个示例,实际上 FileTimeToSystemTime 函数并不是用来设置 FILETIME 值的,  
// 这里只是为了说明你可能如何获取 FILETIME 值。在实际情况中,你会从文件或系统调用中获取这些值。
(7)使用时的注意事项

  1. 确保传递给 CompareFileTime 函数的 FILETIME 结构体是有效的,并且包含了有效的时间信息。
  2. 如果 FILETIME 结构体是通过系统调用(如 GetFileTime)获取的,确保在调用 CompareFileTime 之前这些调用是成功的。
  3. CompareFileTime 函数仅比较 FILETIME 结构体中的时间信息,不考虑 FILETIME 结构体可能包含的其他信息或标志。
  4. 在多线程环境中使用 FILETIME 结构体时,请确保适当的同步机制以防止竞态条件。
  5. 如果 FILETIME 结构体来自不同的系统或不同的时间源,请确保它们在比较之前已经转换为相同的时区或参考时间。

3.3 函数名:CopyFile

(1)函数的概述
CopyFile 是一个 Windows API 函数,用于将一个文件复制到另一个位置,可以创建目标文件的一个新副本。如果目标文件已存在,它可能会被覆盖,除非指定了特定的标志来防止这种情况。

(2)函数所在的动态链接库
CopyFile 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL CopyFile(  
  LPCTSTR lpExistingFileName,  // 现有文件的名称  
  LPCTSTR lpNewFileName,       // 新文件的名称  
  BOOL    bFailIfExists       // 如果新文件已存在时的操作  
);


(4)各参数及返回值的详细解释

  • lpExistingFileName:指向要复制文件的完整路径的字符串。
  • lpNewFileName:指向新文件的完整路径的字符串。这将是复制操作的目标位置。
  • bFailIfExists:如果目标文件已存在,则此参数控制函数的行为。如果为 TRUE,则函数将失败并返回 FALSE。如果为 FALSE,则目标文件将被覆盖。
  • 返回值:如果函数成功,返回值为非零。如果函数失败,返回值为零。要获取更详细的错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
CopyFile 函数的作用是将一个文件的内容复制到另一个位置。这包括文件的所有属性和内容。如果目标文件已存在且 bFailIfExists 设置为 FALSE,则目标文件将被覆盖。如果 bFailIfExists 设置为 TRUE 并且目标文件已存在,则函数将失败并返回 FALSE。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 源文件和目标文件的路径  
    const char* sourceFile = "C:\\path\\to\\source\\file.txt";  
    const char* destFile = "C:\\path\\to\\destination\\file.txt";  
  
    // 尝试复制文件  
    BOOL result = CopyFile(sourceFile, destFile, FALSE); // 如果目标文件已存在,则覆盖它  
  
    if (result) {  
        std::cout << "File copied successfully." << std::endl;  
    } else {  
        DWORD errorCode = GetLastError();  
        std::cerr << "CopyFile failed with error: " << errorCode << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保源文件存在并且可读。
  2. 确保目标路径存在,或者你有权限在目标位置创建新文件和目录。
  3. 如果目标文件已存在并且你不希望它被覆盖,确保将 bFailIfExists 设置为 TRUE。
  4. 在多线程环境中,如果多个线程尝试同时写入同一个文件,可能会导致数据损坏或不可预测的行为。
  5. 当处理文件路径时,请确保路径字符串正确无误,并考虑使用宽字符(LPCTSTR 中的 T)以支持 Unicode 路径。
  6. 如果源文件或目标文件位于网络位置,可能需要额外的权限或网络访问。
  7. 在调用 GetLastError 函数获取错误代码时,请确保在调用其他 API 函数之前进行,因为后续函数调用可能会覆盖错误代码。

3.4 函数名:CreateDirectory

(1)函数的概述
CreateDirectory 是一个 Windows API 函数,用于在文件系统中创建一个新的目录(文件夹)。如果目录的父目录不存在,该函数会尝试创建它们。

(2)函数所在的动态链接库
CreateDirectory 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL CreateDirectory(  
  LPCTSTR lpPathName,     // 要创建的目录的路径  
  LPSECURITY_ATTRIBUTES lpSecurityAttributes // 安全属性,可以设为NULL  
);

(4)各参数及返回值的详细解释

  • lpPathName:一个指向以 null 结尾的字符串的指针,该字符串指定了要创建的目录的路径。路径可以是相对路径或绝对路径。
  • lpSecurityAttributes:一个指向 SECURITY_ATTRIBUTES 结构体的指针,该结构体决定了新目录的安全属性。通常可以设置为 NULL,以使用默认的安全属性。
  • 返回值:如果函数成功,返回值是非零的。如果函数失败,返回值是零。要获取更多错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
CreateDirectory 函数的主要作用是创建一个或多个新目录。如果指定的路径中的任何目录都不存在,则它们都会被创建。但是,如果目录的父目录不存在,并且 lpSecurityAttributes 参数没有指定适当的容器继承标志,那么 CreateDirectory 可能会失败。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 要创建的目录路径  
    const char* directoryPath = "C:\\path\\to\\new\\directory";  
  
    // 尝试创建目录  
    BOOL result = CreateDirectory(directoryPath, NULL);  
  
    if (result) {  
        std::cout << "Directory created successfully." << std::endl;  
    } else {  
        DWORD errorCode = GetLastError();  
        std::cerr << "CreateDirectory failed with error: " << errorCode << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保你有足够的权限在指定的路径上创建目录。
  2. 检查返回值以确保目录已成功创建。如果失败,使用 GetLastError 函数来获取更多信息。
  3. 如果目录的父目录不存在,并且没有指定适当的容器继承标志,CreateDirectory 可能会失败。
  4. 在多线程环境中,请确保对文件系统的访问是同步的,以避免竞态条件。
  5. 如果路径名包含非法字符或格式不正确,函数可能会失败。
  6. 如果目标驱动器已满或已达到文件系统限制(如最大目录数),则函数可能也会失败。

3.5 函数名:CreateFile

(1)函数的概述
CreateFile 是一个功能强大的 Windows API 函数,用于创建或打开文件或 I/O 设备,并返回一个可以用来访问文件的句柄。通过此句柄,可以对文件进行读写、锁定、查询等操作。

(2)函数所在的动态链接库
CreateFile 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

HANDLE CreateFile(  
  LPCTSTR               lpFileName,  // 文件或设备的名称  
  DWORD                 dwDesiredAccess,  // 访问模式(读、写等)  
  DWORD                 dwShareMode,  // 共享模式  
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // 安全属性(可以为 NULL)  
  DWORD                 dwCreationDisposition,  // 创建方式(创建、打开等)  
  DWORD                 dwFlagsAndAttributes,  // 文件属性及标志  
  HANDLE                hTemplateFile  // 模板文件的句柄(可以为 NULL)  
);

(4)各参数及返回值的详细解释

  • lpFileName:要创建或打开的文件的名称。可以是相对路径或绝对路径。
  • dwDesiredAccess:请求的文件访问权限,如 GENERIC_READ、GENERIC_WRITE 等。
  • dwShareMode:指定文件可以被其他进程共享的方式,如 FILE_SHARE_READ、FILE_SHARE_WRITE 等。
  • lpSecurityAttributes:一个指向 SECURITY_ATTRIBUTES 结构的指针,用于设置文件的安全属性。如果此参数为 NULL,则使用默认的安全属性。
  • dwCreationDisposition:指定文件应该如何被创建或打开,例如 CREATE_NEW(如果文件已存在则失败)、CREATE_ALWAYS(总是创建新文件)、OPEN_EXISTING(打开现有文件)等。
  • dwFlagsAndAttributes:文件的属性和标志,如 FILE_ATTRIBUTE_NORMAL(正常文件)、FILE_ATTRIBUTE_HIDDEN(隐藏文件)等,以及文件系统的控制标志,如 FILE_FLAG_OVERLAPPED(用于异步 I/O)。
  • hTemplateFile:如果文件被创建并且此参数非 NULL,则指定一个文件句柄,新创建的文件将从这个句柄复制文件扩展属性。通常设置为 NULL。
  • 返回值:如果函数成功,返回值是一个打开文件的句柄。如果函数失败,返回值是 INVALID_HANDLE_VALUE。要获取更多错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
CreateFile 函数的主要作用是创建或打开一个文件,并返回一个可以用来进行后续文件操作(如读写、锁定等)的句柄。它提供了非常灵活的参数设置,允许用户指定文件的访问权限、共享模式、创建方式、属性及标志等。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 文件路径  
    const char* filePath = "C:\\path\\to\\file.txt";  
  
    // 尝试创建或打开文件  
    HANDLE hFile = CreateFile(  
        filePath,            // 文件路径  
        GENERIC_READ | GENERIC_WRITE, // 读写权限  
        0,                   // 不共享  
        NULL,                // 默认安全属性  
        CREATE_ALWAYS,       // 如果文件存在则覆盖,不存在则创建  
        FILE_ATTRIBUTE_NORMAL,// 正常文件  
        NULL                 // 没有模板文件  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        DWORD error = GetLastError();  
        std::cerr << "CreateFile failed with error: " << error << std::endl;  
    } else {  
        std::cout << "File created or opened successfully." << std::endl;  
        // 在这里可以进行文件操作...  
        CloseHandle(hFile); // 完成后关闭句柄  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 在使用 CreateFile 函数后,无论成功还是失败,都应该通过调用 CloseHandle 函数来关闭返回的句柄,以避免资源泄露。
  2. 当指定文件访问权限时,要确保请求的权限是合理的,并考虑到其他可能访问该文件的进程的需求。
  3. 在多线程环境中,要特别注意对文件的同步访问,以避免数据不一致或其他并发问题。
  4. 如果文件位于网络位置或需要特殊权限才能访问,请确保程序有足够的权限来执行操作。
  5. 在调用 GetLastError 函数获取错误信息时,请确保在调用其他可能修改错误代码的 API 函数之前进行。

3.6 函数名:CreateFileMapping

(1)函数的概述
CreateFileMapping 函数用于在调用进程的地址空间中为文件数据(或物理存储设备)创建一个文件映射对象。这个对象可以随后被映射到一个或多个进程的地址空间中,使得这些进程可以像访问内存一样访问文件数据。

(2)函数所在的动态链接库
CreateFileMapping 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

HANDLE CreateFileMapping(  
  HANDLE hFile,              // 用于创建映射文件的文件句柄  
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全属性(可以为 NULL)  
  DWORD flProtect,            // 页面保护标志  
  DWORD dwMaximumSizeHigh,    // 文件映射对象的高32位大小  
  DWORD dwMaximumSizeLow,     // 文件映射对象的低32位大小  
  LPCTSTR lpName              // 文件映射对象的名称(可以为 NULL)  
);

(4)各参数及返回值的详细解释

  • hFile:一个打开文件的句柄。如果此参数为 INVALID_HANDLE_VALUE,则系统将创建一个可以映射到物理存储设备的文件映射对象。
  • lpFileMappingAttributes:一个指向 SECURITY_ATTRIBUTES 结构的指针,该结构决定了返回的句柄是否可以被子进程继承,以及文件映射对象的安全描述符。如果此参数为 NULL,则句柄不可以被子进程继承,并使用默认的安全描述符。
  • flProtect:页面保护标志,指定文件映射对象的页面保护属性,例如 PAGE_READONLY(只读)、PAGE_READWRITE(读写)等。
  • dwMaximumSizeHigh:文件映射对象大小的高32位。如果文件映射对象将用于映射一个文件,则此值应与文件的大小相匹配或大于文件的大小。
  • dwMaximumSizeLow:文件映射对象大小的低32位。
  • lpName:文件映射对象的名称。如果此参数为 NULL,则创建的对象是一个私有对象。否则,它是一个命名对象,可以在多个进程间共享。
  • 返回值:如果函数成功,则返回值是一个指向文件映射对象的句柄。如果函数失败,则返回值为 NULL。

(5)函数的详细作用
CreateFileMapping 函数的作用是创建一个文件映射对象,该对象可以用于将一个文件或物理存储设备映射到进程的地址空间中,使得进程可以直接访问这些资源,就像访问内存一样。这对于高效的文件读写操作、共享内存等场景非常有用。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 打开一个文件  
    HANDLE hFile = CreateFile(  
        "C:\\path\\to\\file.txt",  // 文件路径  
        GENERIC_READ | GENERIC_WRITE, // 读写权限  
        0,                           // 不共享  
        NULL,                        // 默认安全属性  
        OPEN_EXISTING,               // 打开现有文件  
        FILE_ATTRIBUTE_NORMAL,       // 正常文件  
        NULL                         // 没有模板文件  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed." << std::endl;  
        return 1;  
    }  
  
    // 创建一个文件映射对象  
    HANDLE hFileMapping = CreateFileMapping(  
        hFile,                       // 使用的文件句柄  
        NULL,                        // 默认安全属性  
        PAGE_READWRITE,              // 读写保护  
        0,                           // 文件映射对象的高32位大小为0  
        0,                           // 文件映射对象的低32位大小也为0(使用文件大小)  
        NULL                         // 私有对象,没有名称  
    );  
  
    if (hFileMapping == NULL) {  
        std::cerr << "CreateFileMapping failed." << std::endl;  
        CloseHandle(hFile); // 关闭文件句柄  
        return 1;  
    }  
  
    // ... 在这里可以继续使用 hFileMapping 进行内存映射等操作 ...  
  
    // 清理资源  
    CloseHandle(hFileMapping); // 关闭文件映射对象句柄  
    CloseHandle(hFile);        // 关闭文件句柄  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保传递给 CreateFileMapping 的文件句柄是有效的,并且该文件是打开的。
  2. 如果文件映射对象将用于映射一个文件,请确保指定的文件大小(通过 dwMaximumSizeHigh 和 dwMaximumSizeLow)与文件实际大小相匹配或大于文件大小。
  3. 在使用完文件映射对象后,应通过调用 CloseHandle 函数来关闭其句柄,以避免资源泄露。
  4. 如果 CreateFileMapping 函数成功,但在后续操作中(如 MapViewOfFile)失败,请确保正确释放所有已分配的资源。

3.6 函数名:DeleteFile

(1)函数的概述
DeleteFile 函数用于删除指定名称的文件。如果文件是只读、隐藏或系统文件,函数将尝试删除它,但操作系统可能会阻止该操作。如果文件正在被其他进程使用,函数将失败。

(2)函数所在的动态链接库
DeleteFile 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL DeleteFile(  
  LPCTSTR lpFileName  // 要删除的文件名或路径  
);

(4)各参数及返回值的详细解释

  • lpFileName:一个指向要删除的文件或目录的路径的字符串的指针。这个字符串可以是相对路径或绝对路径。
  • 返回值:
  • 如果函数成功,返回值是非零。
  • 如果函数失败,返回值是零。要获取扩展的错误信息,可以调用 GetLastError 函数。
  • (5)函数的详细作用
  • DeleteFile 函数的主要作用是删除指定路径下的文件。如果文件成功被删除,系统将不再保留该文件的任何数据,并且该文件的任何句柄都将变得无效。但是,如果文件正在被其他进程使用,或者由于其他原因(如权限不足)而无法删除,则 DeleteFile 将失败。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 要删除的文件名  
    const char* fileName = "C:\\path\\to\\file.txt";  
  
    // 尝试删除文件  
    BOOL result = DeleteFile(fileName);  
  
    if (result) {  
        std::cout << "File deleted successfully." << std::endl;  
    } else {  
        std::cerr << "DeleteFile failed. Error code: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保你有足够的权限来删除指定的文件。
  2. 如果文件正在被其他进程使用,DeleteFile 将失败。确保在调用 DeleteFile 之前,文件没有被其他进程锁定或打开。
  3. 调用 DeleteFile 后,任何指向该文件的句柄都将变得无效。如果其他代码段或进程仍然持有这些句柄,并尝试使用它们,可能会导致未定义的行为。
  4. 如果文件不存在,DeleteFile 通常会成功,并且不返回错误。因此,在调用 DeleteFile 之前检查文件是否存在可能是不必要的。
  5. DeleteFile 只能用于删除文件,不能用于删除目录。如果尝试删除目录,它将失败并返回错误。
  6. 在多线程环境中,请确保对文件访问的同步,以避免在 DeleteFile 调用时发生竞争条件。

3.7 函数名:DeviceIoControl

(1)函数的概述
DeviceIoControl 函数是一个Windows API函数,用于对设备驱动程序发送控制代码和输入/输出数据。它允许应用程序与设备驱动程序进行通信,以执行设备特定的操作,如读取设备的状态、发送命令到设备、配置设备参数等。

(2)函数所在的动态链接库
DeviceIoControl 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL DeviceIoControl(  
  HANDLE hDevice,             // 设备的句柄  
  DWORD dwIoControlCode,     // 控制代码  
  LPVOID lpInBuffer,         // 输入数据缓冲区  
  DWORD nInBufferSize,       // 输入数据缓冲区的大小  
  LPVOID lpOutBuffer,        // 输出数据缓冲区  
  DWORD nOutBufferSize,      // 输出数据缓冲区的大小  
  LPDWORD lpBytesReturned,   // 接收的字节数  
  LPOVERLAPPED lpOverlapped  // OVERLAPPED结构的指针(用于异步I/O)  
);

(4)各参数及返回值的详细解释

  • hDevice:设备的句柄,通常是通过 CreateFile 函数获得的。
  • dwIoControlCode:控制代码,用于指定要执行的操作。这个值通常由设备驱动程序的文档定义。
  • lpInBuffer:指向输入数据缓冲区的指针。如果不需要输入数据,则为NULL。
  • nInBufferSize:输入数据缓冲区的大小(以字节为单位)。如果不需要输入数据,则为0。
  • lpOutBuffer:指向输出数据缓冲区的指针。如果不需要输出数据,则为NULL。
  • nOutBufferSize:输出数据缓冲区的大小(以字节为单位)。如果不需要输出数据,则为0。
  • lpBytesReturned:指向一个DWORD的指针,用于接收从设备驱动程序返回的实际字节数。如果lpOverlapped为NULL,并且操作不是异步的,则此参数必须是非NULL。
  • lpOverlapped:指向一个OVERLAPPED结构的指针,用于异步I/O操作。如果此参数为NULL,则操作是同步的。
  • 返回值:如果操作成功,返回值为非零;如果操作失败,返回值为0,可以调用 GetLastError 函数来获取扩展错误信息。

(5)函数的详细作用
DeviceIoControl 函数允许应用程序与设备驱动程序进行通信,以执行设备特定的操作。这些操作可能包括读取设备的状态、发送命令到设备、配置设备参数等。通过发送不同的控制代码和输入/输出数据,应用程序可以控制设备的各种行为。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
// 假设我们有一个设备控制代码和相关的数据结构  
#define MY_DEVICE_CONTROL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)  
  
// 示例数据结构  
typedef struct {  
    DWORD SomeData;  
} MY_DEVICE_DATA, *PMY_DEVICE_DATA;  
  
int main() {  
    HANDLE hDevice = CreateFile(  
        TEXT("\\\\.\\MyDevice"), // 设备的名称,这只是一个示例  
        0,                      // 不需要访问权限  
        0,                      // 共享模式  
        NULL,                   // 默认安全属性  
        OPEN_EXISTING,          // 现有设备  
        0,                      // 文件属性  
        NULL                    // 模板文件  
    );  
  
    if (hDevice == INVALID_HANDLE_VALUE) {  
        std::cerr << "Failed to open device." << std::endl;  
        return 1;  
    }  
  
    MY_DEVICE_DATA inData = { 123 }; // 示例输入数据  
    DWORD bytesReturned = 0;  
    BOOL result = DeviceIoControl(  
        hDevice,  
        MY_DEVICE_CONTROL_CODE,  
        &inData,  
        sizeof(inData),  
        NULL, // 不需要输出数据  
        0,    // 输出缓冲区大小为0  
        &bytesReturned,  
        NULL  // 同步操作  
    );  
  
    if (!result) {  
        std::cerr << "DeviceIoControl failed. Error: " << GetLastError() << std::endl;  
    } else {  
        std::cout << "DeviceIoControl succeeded. Bytes returned: " << bytesReturned << std::endl;  
    }  
  
    CloseHandle(hDevice);  
    return 0;  
}

(7)使用时的注意事项

  1. 确保你有足够的权限来访问设备。
  2. 设备的名称(例如上面的\\\\.\\MyDevice)应该是设备驱动程序定义的。这通常是一个特殊的路径,如 \\.\MyDevice,其中 MyDevice 是设备驱动程序的名称或别名。
  3. 控制代码的正确性:dwIoControlCode 参数是发送到设备驱动程序的控制代码。这个代码必须与设备驱动程序文档中定义的一致。错误的控制代码可能导致函数失败或设备的不正确行为。
  4. 缓冲区大小和安全性:确保 lpInBuffer 和 lpOutBuffer 指向的缓冲区足够大,以容纳输入和输出数据。此外,当处理来自外部源(如设备驱动程序)的数据时,应注意数据的安全性,以防止缓冲区溢出等安全问题。
  5. 错误处理:如果 DeviceIoControl 函数失败,应调用 GetLastError 函数来获取错误代码,并根据需要进行适当的错误处理。
  6. 同步和异步操作:如果指定了 lpOverlapped 参数并且它不是 NULL,则 DeviceIoControl 函数将进行异步操作。在异步操作中,函数会立即返回,而不管操作是否完成。应使用其他机制(如事件对象、等待函数等)来检查操作是否完成并获取结果。
  7. 关闭句柄:在不再需要访问设备时,应使用 CloseHandle 函数关闭设备句柄,以释放系统资源。
  8. 兼容性和平台特定性:请注意,DeviceIoControl 函数是Windows平台特有的,并且其行为可能因不同的Windows版本和设备驱动程序而异。在跨平台或面向未来版本的代码中,应谨慎使用此函数,并考虑使用更通用的解决方案(如果可用)。
  9. 调试和日志记录:在开发和调试过程中,使用日志记录或调试工具来跟踪 DeviceIoControl 函数的调用和结果可能会很有帮助。这可以帮助识别问题并加快解决速度。

3.8 函数名:DosDateTimeToFileTime

(1)函数的概述
DosDateTimeToFileTime 函数用于将DOS日期和时间格式转换为Windows FILETIME格式。DOS日期和时间格式是一种简单的日期和时间表示方式,而FILETIME则是一个更复杂的64位值,表示自1601年1月1日午夜(UTC)以来的100纳秒间隔数。

(2)函数所在的动态链接库
DosDateTimeToFileTime 函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL DosDateTimeToFileTime(  
  WORD wFatDate,        // DOS日期  
  WORD wFatTime,        // DOS时间  
  LPFILETIME lpFileTime // FILETIME结构的指针  
);

(4)各参数及返回值的详细解释

  • wFatDate:DOS日期。它是一个WORD值,通常是由日期三部分(年、月、日)组合而成的。
  • wFatTime:DOS时间。它也是一个WORD值,由小时、分钟、秒(以及可能的秒的一部分)组合而成。
  • lpFileTime:指向FILETIME结构的指针,用于接收转换后的FILETIME值。
  • 返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。要获取扩展的错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
DosDateTimeToFileTime 函数的主要作用是将旧的DOS日期和时间格式转换为Windows FILETIME格式。这通常在处理旧的FAT文件系统(如FAT12、FAT16和FAT32)上的文件或目录时很有用,因为这些文件系统使用DOS日期和时间格式来存储文件和目录的创建、修改和访问时间。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 示例DOS日期和时间值  
    WORD wFatDate = 0x419B; // 假设为2021年9月1日的DOS日期编码  
    WORD wFatTime = 0x1234; // 假设为10:30:20的DOS时间编码(注意:这不是真实的编码方式,只是示例)  
  
    FILETIME ft;  
    BOOL result = DosDateTimeToFileTime(wFatDate, wFatTime, &ft);  
  
    if (result) {  
        // 转换成功,可以在这里使用ft变量  
        // 注意:FILETIME是一个64位值,通常不会直接打印,但可以转换为SYSTEMTIME进行显示  
        SYSTEMTIME st;  
        FileTimeToSystemTime(&ft, &st);  
        std::wcout << L"Converted Date/Time: " << st.wYear << L"-"   
                    << std::setfill(L'0') << std::setw(2) << st.wMonth << L"-"   
                    << std::setfill(L'0') << std::setw(2) << st.wDay << L" "   
                    << std::setfill(L'0') << std::setw(2) << st.wHour << L":"   
                    << std::setfill(L'0') << std::setw(2) << st.wMinute << L":"   
                    << std::setfill(L'0') << std::setw(2) << st.wSecond << std::endl;  
    } else {  
        std::cerr << "DosDateTimeToFileTime failed. Error: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. DOS日期和时间的编码方式可能因文件系统或实现而异。上面的示例中提供的 wFatDate 和 wFatTime 值是假设的,并不是真正的DOS日期和时间编码。在实际应用中,你需要从FAT文件系统的元数据中获取这些值,并了解如何正确解释它们。
  2. FILETIME是一个64位值,通常不会直接用于显示或比较。如果你需要将FILETIME转换为人类可读的日期和时间格式,可以使用 FileTimeToSystemTime 函数将其转换为 SYSTEMTIME 结构。
  3. 在调用 DosDateTimeToFileTime 时,请确保提供的 lpFileTime 参数是一个有效的、非NULL的指针,以避免潜在的空指针解引用错误。
  4. 检查函数的返回值以确认转换是否成功,并在必要时调用 GetLastError 函数来获取更详细的错误信息。

3.9 函数名:FileTimeToDosDateTime

(1)函数的概述
FileTimeToDosDateTime 函数用于将Windows FILETIME结构转换为DOS日期和时间格式。DOS日期和时间格式通常用于FAT文件系统中存储文件或目录的日期和时间戳。

(2)函数所在的动态链接库
该函数位于Windows系统的Kernel32.dll动态链接库中。

(3)函数的原型

BOOL FileTimeToDosDateTime(  
  const FILETIME *lpFileTime, // 指向FILETIME结构的指针  
  LPWORD lpFatDate,          // 指向WORD的指针,用于接收DOS日期  
  LPWORD lpFatTime           // 指向WORD的指针,用于接收DOS时间  
);

(4)各参数及返回值的详细解释

  • lpFileTime:指向FILETIME结构的指针,表示要转换的Windows FILETIME时间。
  • lpFatDate:指向WORD的指针,用于接收转换后的DOS日期值。
  • lpFatTime:指向WORD的指针,用于接收转换后的DOS时间值。
  • 返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。要获取扩展的错误信息,可以调用GetLastError函数。

(5)函数的详细作用
FileTimeToDosDateTime函数的主要作用是将一个表示协调世界时(UTC)的64位FILETIME值(自1601年1月1日以来的100纳秒间隔数)转换为DOS日期和时间格式。DOS日期和时间是一个16位的值,其中高16位表示日期,低16位表示时间。由于这种格式的限制,它不能表示超过1999年的日期。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 示例FILETIME值(这里应该是从某处获取的)  
    FILETIME ft = { 0xD1CB1E18, 0x01D21382 }; // 这只是一个示例值  
  
    WORD dosDate, dosTime;  
    BOOL result = FileTimeToDosDateTime(&ft, &dosDate, &dosTime);  
  
    if (result) {  
        std::cout << "DOS Date: " << std::hex << dosDate << ", DOS Time: " << std::hex << dosTime << std::endl;  
        // 注意:这里只是输出了16进制表示,实际上你可能需要进一步解析这些值以获取年、月、日、时、分、秒等  
    } else {  
        std::cerr << "FileTimeToDosDateTime failed. Error: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 转换可能不是完全可逆的,因为DOS日期和时间格式有其局限性(例如,年份限制在1980年至1999年之间)。
  2. 如果FILETIME值表示的时间超出了DOS日期和时间格式能够表示的范围,则转换结果将是未定义的。
  3. 在调用FileTimeToDosDateTime之前,请确保lpFileTime、lpFatDate和lpFatTime参数指向有效的内存位置。
  4. 检查函数的返回值以确保转换成功,并在需要时调用GetLastError以获取错误代码。
  5. 如果你需要将DOS日期和时间格式转换回人类可读的日期和时间字符串,你可能需要编写额外的代码来解析DOS日期和时间值,或者使用其他API(如DosDateTimeToSystemTime)进行转换。

3.10 函数名:FileTimeToLocalFileTime

(1)函数的概述
FileTimeToLocalFileTime 函数用于将表示协调世界时(UTC)的 FILETIME 结构转换为表示本地时间的 FILETIME 结构。它考虑了当前系统的时区设置和夏令时(如果适用)的影响。

(2)函数所在的动态链接库
该函数位于 Windows 系统的 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL FileTimeToLocalFileTime(  
  const FILETIME *lpFileTime,    // 指向FILETIME结构的指针,表示UTC时间  
  LPFILETIME lpLocalFileTime     // 指向FILETIME结构的指针,用于接收本地时间  
);

(4)各参数及返回值的详细解释

  • lpFileTime:指向 FILETIME 结构的指针,该结构包含要转换的 UTC 时间。
  • lpLocalFileTime:指向 FILETIME 结构的指针,该结构将接收转换后的本地时间。
  • 返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。要获取扩展的错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
FileTimeToLocalFileTime 函数用于在需要考虑本地时区的情况下,将 UTC 时间转换为本地时间。这在处理跨时区的时间戳或显示给用户的时间戳时特别有用。它确保转换后的时间与当前系统的时区设置相匹配。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 示例FILETIME值(UTC时间),这里仅为演示  
    FILETIME utcFileTime = { 0xD1CB1E18, 0x01D21382 };  
  
    // 用于存储本地时间的FILETIME变量  
    FILETIME localFileTime;  
  
    // 转换UTC时间为本地时间  
    BOOL result = FileTimeToLocalFileTime(&utcFileTime, &localFileTime);  
  
    if (result) {  
        // 在这里,localFileTime包含了转换后的本地时间,但通常不会直接打印FILETIME值  
        // 如果需要,可以将其转换为SYSTEMTIME以便显示  
        SYSTEMTIME st;  
        if (FileTimeToSystemTime(&localFileTime, &st)) {  
            std::wcout << L"Local Time: " << st.wYear << L"-"  
                       << std::setfill(L'0') << std::setw(2) << st.wMonth << L"-"  
                       << std::setfill(L'0') << std::setw(2) << st.wDay << L" "  
                       << std::setfill(L'0') << std::setw(2) << st.wHour << L":"  
                       << std::setfill(L'0') << std::setw(2) << st.wMinute << L":"  
                       << std::setfill(L'0') << std::setw(2) << st.wSecond << std::endl;  
        } else {  
            std::cerr << "FileTimeToSystemTime failed. Error: " << GetLastError() << std::endl;  
        }  
    } else {  
        std::cerr << "FileTimeToLocalFileTime failed. Error: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保在调用 FileTimeToLocalFileTime 之前,lpFileTime 和 lpLocalFileTime 参数都指向有效的内存位置。
  2. 检查函数的返回值以确保转换成功,并在需要时调用 GetLastError 以获取错误代码。
  3. 转换后的本地时间将取决于系统的时区设置,因此如果在不同的时区运行相同的代码,可能会得到不同的结果。
  4. 如果你的应用程序需要在多个时区之间处理时间戳,你可能需要考虑使用 UTC 时间来避免时区转换带来的复杂性。

3.11 函数名:FileTimeToSystemTime

(1)函数的概述
FileTimeToSystemTime函数是Windows API中的一个函数,用于将一个FILETIME结构转换为SYSTEMTIME结构。FILETIME是以100纳秒为单位的64位值,表示自1601年1月1日以来的时间。SYSTEMTIME则是一个更人性化的时间表示方式,包含了年、月、日、小时等详细时间单位。

(2)函数所在的动态链接库
FileTimeToSystemTime函数位于Kernel32.dll动态链接库中。

(3)函数的原型

BOOL FileTimeToSystemTime(  
  const FILETIME *lpFileTime,  
  LPSYSTEMTIME lpSystemTime  
);

(4)各参数及返回值的详细解释

  • lpFileTime:指向一个FILETIME结构的指针,该结构包含要转换的时间。
  • lpSystemTime:指向一个SYSTEMTIME结构的指针,该结构用于接收转换后的时间。
  • 返回值:如果函数成功,返回值为非零;如果函数失败,返回值为0。要获取扩展的错误信息,可以调用GetLastError函数。

(5)函数的详细作用
FileTimeToSystemTime函数的主要作用是将难以直观理解的FILETIME格式时间转换为更易于阅读和理解的SYSTEMTIME格式时间。SYSTEMTIME结构中的各个字段(年、月、日、小时等)可以直接用于显示或进行日期时间的计算。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    FILETIME ft;  
    SYSTEMTIME st;  
      
    // 假设ft已经被赋予了一个有效的FILETIME值  
    // ...  
  
    if (FileTimeToSystemTime(&ft, &st)) {  
        std::cout << "The converted system time is: "   
                  << st.wYear << "-" << st.wMonth << "-" << st.wDay << " "  
                  << st.wHour << ":" << st.wMinute << ":" << st.wSecond << std::endl;  
    } else {  
        std::cerr << "FileTimeToSystemTime failed with error " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 在调用FileTimeToSystemTime之前,应确保FILETIME结构包含有效的时间值。
  2. 必须为SYSTEMTIME结构分配足够的内存空间,并确保传递给函数的指针是有效的。
  3. 应检查函数的返回值以确定转换是否成功,如果不成功,应使用GetLastError函数来获取错误代码,以便进行故障排除。
  4. 考虑到跨平台或不同系统的兼容性,如果代码需要在非Windows系统上运行,应避免使用特定于Windows的API函数。
  5. 请注意,上述解释和示例代码是基于Windows平台的,如果你在其他操作系统上编程,你需要查找相应平台的时间处理函数或库。

3.12 函数名:FindClose

(1)函数的概述
FindClose是一个Windows API函数,用于关闭由FindFirstFile或FindNextFile函数打开的搜索句柄。

(2)函数所在的动态链接库
FindClose函数位于Kernel32.dll动态链接库中。

(3)函数的原型

BOOL FindClose(HANDLE hFindFile);

(4)各参数及返回值的详细解释

  • 参数:
  • hFindFile:这是由FindFirstFile或FindFirstFileEx函数返回的搜索句柄。
  • 返回值:
  • 如果函数成功,返回值为非零。
  • 如果函数失败,返回值为零。要获取扩展的错误信息,可以调用GetLastError。

(5)函数的详细作用
FindClose函数用于关闭指定的搜索句柄,释放与之相关的系统资源。在使用FindFirstFile或FindFirstFileEx开始文件搜索后,应始终使用FindClose来关闭搜索句柄,以避免资源泄漏。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    WIN32_FIND_DATA ffd;  
    HANDLE hFind = FindFirstFile(TEXT("C:\\*"), &ffd);  
  
    if (hFind == INVALID_HANDLE_VALUE) {  
        std::cerr << "FindFirstFile failed" << std::endl;  
        return 1;  
    }  
  
    // ... 可以在这里使用FindNextFile继续搜索文件 ...  
  
    // 关闭搜索句柄  
    if (!FindClose(hFind)) {  
        std::cerr << "FindClose failed" << std::endl;  
        return 1;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保在使用完搜索句柄后总是调用FindClose,以释放系统资源。
  2. 如果FindClose函数调用失败,应检查GetLastError返回的错误代码以确定失败的原因。
  3. 不要在多线程环境中共享搜索句柄,除非采取了适当的同步措施。
  4. 搜索句柄在使用完毕后应尽快关闭,以避免无谓地占用系统资源。

3.13 函数名:FindFirstFile

(1)函数的概述
FindFirstFile是Windows API中的一个函数,它用于搜索指定路径下的第一个文件或子目录,并返回一个句柄,该句柄可用于后续的FindNextFile和FindClose函数调用。

(2)函数所在的动态链接库
FindFirstFile函数位于Kernel32.dll动态链接库中。

(3)函数的原型

HANDLE FindFirstFile(  
  LPCTSTR           lpFileName,  
  LPWIN32_FIND_DATA lpFindFileData  
);

(4)各参数及返回值的详细解释

  • lpFileName:一个指向要搜索的路径名的字符串指针。可以指定路径为文件夹路径加上通配符,例如:"C:\MyFolder*.*" 表示搜索"C:\MyFolder"路径下的所有文件和文件夹。
  • lpFindFileData:一个指向WIN32_FIND_DATA结构的指针,该结构用于接收找到的文件或文件夹的信息。
  • 返回值:如果函数成功,返回值是一个搜索句柄,可用于FindNextFile和FindClose函数。如果函数失败,返回值为INVALID_HANDLE_VALUE。

(5)函数的详细作用
FindFirstFile函数开始在一个目录中进行文件搜索,并将搜索到的第一个文件或目录的信息放入WIN32_FIND_DATA结构中。这个结构包含了文件/目录的名称、大小、属性、创建时间、最后访问时间和最后修改时间等信息。通过这个函数,可以遍历一个目录下的所有文件和子目录。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    WIN32_FIND_DATA ffd;  
    HANDLE hFind = FindFirstFile(TEXT("C:\\MyFolder*.*"), &ffd);  
  
    if (hFind == INVALID_HANDLE_VALUE) {  
        std::cerr << "FindFirstFile failed" << std::endl;  
        return 1;  
    }  
  
    do {  
        std::wcout << ffd.cFileName << std::endl;  
    } while (FindNextFile(hFind, &ffd) != 0);  
  
    FindClose(hFind);  
    return 0;  
}

(7)使用时的注意事项

  1. 在使用完搜索句柄后,应调用FindClose来关闭句柄,以避免资源泄漏。
  2. 如果在调用FindFirstFile或FindNextFile时发生错误,可以通过调用GetLastError函数来获取具体的错误代码。
  3. 搜索时,路径字符串中的通配符*和?可用于匹配文件名和扩展名。例如,*.*匹配所有文件和文件夹,而*.txt只匹配文本文件。
  4. 返回值INVALID_HANDLE_VALUE表示搜索失败,应检查错误原因。
  5. WIN32_FIND_DATA结构体中的cFileName成员以空字符结尾,可以直接用作字符串处理。
  6. 如果搜索的是文件夹而非文件,需要检查WIN32_FIND_DATA结构体中的dwFileAttributes成员是否包含FILE_ATTRIBUTE_DIRECTORY标志来判断。

3.14 函数名:FindNextFile

(1)函数的概述
FindNextFile函数用于继续搜索由FindFirstFile函数开始的文件搜索操作,它用于查找下一个文件或子目录。

(2)函数所在的动态链接库
FindNextFile函数位于Kernel32.dll动态链接库中。

(3)函数的原型

BOOL FindNextFile(  
  HANDLE hFindFile,  
  LPWIN32_FIND_DATA lpFindFileData  
);

(4)各参数及返回值的详细解释

  • hFindFile:这是由FindFirstFile函数返回的搜索句柄。
  • lpFindFileData:指向WIN32_FIND_DATA结构的指针,用于接收找到的下一个文件或目录的信息。
  • 返回值:如果函数成功找到下一个文件或目录,则返回非零值。如果没有更多的文件或目录,或者出现错误,则返回零。要判断是没有更多的文件还是出现错误,可以调用GetLastError函数,如果返回ERROR_NO_MORE_FILES则表示没有更多的文件。

(5)函数的详细作用
FindNextFile函数用于在由FindFirstFile启动的文件搜索中查找下一个文件或目录。每次调用此函数,它都会检索下一个文件或目录的信息,并将其填充到传入的WIN32_FIND_DATA结构中。通过这种方式,可以遍历整个目录的内容。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    WIN32_FIND_DATA ffd;  
    HANDLE hFind = FindFirstFile(TEXT("C:\\MyFolder*.*"), &ffd);  
  
    if (hFind == INVALID_HANDLE_VALUE) {  
        std::cerr << "FindFirstFile failed" << std::endl;  
        return 1;  
    }  
  
    do {  
        std::wcout << ffd.cFileName << std::endl;  
    } while (FindNextFile(hFind, &ffd)); // 使用FindNextFile查找下一个文件  
  
    DWORD dwError = GetLastError();  
    if (dwError != ERROR_NO_MORE_FILES) { // 检查是否因为没有更多文件而结束  
        std::cerr << "FindNextFile failed with error " << dwError << std::endl;  
        return 2;  
    }  
  
    FindClose(hFind); // 关闭搜索句柄  
    return 0;  
}

(7)使用时的注意事项

  1. 必须确保在使用完搜索句柄后调用FindClose来关闭它,以避免资源泄漏。
  2. 如果FindNextFile返回零,应该调用GetLastError来确定是因为没有更多的文件还是发生了错误。
  3. WIN32_FIND_DATA结构体中的信息是在每次成功调用FindNextFile后更新的,确保在处理完当前文件信息后再调用FindNextFile。
  4. 在多线程环境中使用文件搜索句柄时要特别小心,以避免竞态条件。
  5. 搜索时,应确保传入的路径是有效的,并且应用程序有足够的权限访问该路径。

3.15 函数名:FlushFileBuffers

(1)函数的概述
FlushFileBuffers函数用于将指定文件的数据缓冲区中的数据立即写入磁盘。这可以确保所有挂起的写入操作都已完成,并且数据已经持久化保存到磁盘上。

(2)函数所在的动态链接库
FlushFileBuffers函数位于Kernel32.dll动态链接库中。

(3)函数的原型

BOOL FlushFileBuffers(HANDLE hFile);

(4)各参数及返回值的详细解释

  • hFile:一个句柄,表示要刷新缓冲区的文件。这个文件句柄必须是以写入模式(如GENERIC_WRITE或FILE_WRITE_DATA)打开的。
  • 返回值:如果函数成功执行,返回值为非零。如果函数执行失败,返回值为零。要获取更多的错误信息,可以调用GetLastError函数。

(5)函数的详细作用
FlushFileBuffers函数的作用是确保所有对指定文件的挂起写入操作都已完成,并且数据已经实际写入磁盘。通常,操作系统和文件系统为了提高性能会使用缓存机制,将写入操作延迟执行或合并执行。然而,在某些情况下,为了确保数据的完整性和一致性,可能需要立即将数据写入磁盘,这时候就可以使用FlushFileBuffers函数。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFile(  
        L"example.txt",          // 文件名  
        GENERIC_WRITE,          // 访问模式  
        0,                      // 共享模式  
        NULL,                   // 安全描述符  
        OPEN_ALWAYS,            // 创建处置  
        FILE_ATTRIBUTE_NORMAL,  // 文件属性  
        NULL                    // 模板文件句柄  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed with error " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    const char data[] = "Hello, World!";  
    DWORD bytesWritten;  
    if (!WriteFile(hFile, data, sizeof(data), &bytesWritten, NULL)) {  
        std::cerr << "WriteFile failed with error " << GetLastError() << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    // 刷新文件缓冲区,确保数据写入磁盘  
    if (!FlushFileBuffers(hFile)) {  
        std::cerr << "FlushFileBuffers failed with error " << GetLastError() << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    CloseHandle(hFile);  
    return 0;  
}

(7)使用时的注意事项

  1. 使用FlushFileBuffers会增加磁盘I/O操作,可能会影响程序的性能,因此应谨慎使用。
  2. 如果文件是以异步方式打开的,那么FlushFileBuffers可能无法立即将所有数据写入磁盘,因为它可能需要等待之前的异步操作完成。
  3. FlushFileBuffers函数仅适用于以写入模式打开的文件句柄。
  4. 在调用FlushFileBuffers之后,如果还需要继续写入文件,则无需再次调用FlushFileBuffers,除非需要确保数据再次立即写入磁盘。频繁地刷新缓冲区会降低性能。
  5. 在关闭文件句柄或程序结束时,系统会自动刷新文件缓冲区,但在某些关键场景下,如数据库事务日志、关键配置文件等,可能需要显式调用FlushFileBuffers来确保数据的即时持久化。

3.16 函数名:FlushViewOfFile

(1)函数的概述
FlushViewOfFile函数用于将内存映射文件视图中的数据强制写回到磁盘文件中,以确保对文件视图的所有更改都被保存。

(2)函数所在的动态链接库
FlushViewOfFile函数位于Kernel32.dll动态链接库中。

(3)函数的原型

BOOL FlushViewOfFile(  
  LPCVOID lpBaseAddress,  
  SIZE_T  dwSize  
);

(4)各参数及返回值的详细解释

  • lpBaseAddress:指向要刷新的内存映射文件视图的基地址的指针。
  • dwSize:指定要刷新的视图部分的大小,以字节为单位。如果此参数为0,那么从lpBaseAddress开始的整个视图都会被刷新。
  • 返回值:如果函数成功,返回值为非零值;如果函数失败,返回值为0。要获取更多错误信息,可以调用GetLastError。

(5)函数的详细作用
当应用程序对内存映射文件视图进行修改后,这些修改最初只在内存中,并未立即反映到磁盘文件上。FlushViewOfFile函数的作用就是将内存中的更改强制写回磁盘,以确保数据的持久性。这在需要确保数据完整性和一致性的场景中非常重要,例如数据库或日志文件的更新。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFile(  
        L"example.dat",          // 文件名  
        GENERIC_READ | GENERIC_WRITE, // 读写权限  
        0,                      // 共享模式  
        NULL,                   // 安全描述符  
        OPEN_ALWAYS,            // 创建标志  
        FILE_ATTRIBUTE_NORMAL,  // 文件属性  
        NULL                    // 模板文件句柄  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed." << std::endl;  
        return 1;  
    }  
  
    HANDLE hMapping = CreateFileMapping(  
        hFile,                // 文件句柄  
        NULL,                 // 未使用安全属性  
        PAGE_READWRITE,       // 保护标志  
        0,                    // 最大文件大小的高32位  
        0,                    // 最大文件大小的低32位  
        NULL                  // 映射文件的名称  
    );  
  
    if (hMapping == NULL) {  
        std::cerr << "CreateFileMapping failed." << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    LPVOID lpView = MapViewOfFile(  
        hMapping,             // 文件映射对象的句柄  
        FILE_MAP_WRITE,       // 访问模式,写访问  
        0,                    // 文件偏移量的高32位  
        0,                    // 文件偏移量的低32位  
        0                     // 要映射的字节数(0表示映射整个文件)  
    );  
  
    if (lpView == NULL) {  
        std::cerr << "MapViewOfFile failed." << std::endl;  
        CloseHandle(hMapping);  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    // 假设我们在这里对lpView指向的内存做了一些修改...  
    // ...  
  
    // 现在,我们使用FlushViewOfFile来确保更改被写回文件  
    if (!FlushViewOfFile(lpView, 0)) { // 0表示刷新整个视图  
        std::cerr << "FlushViewOfFile failed with error " << GetLastError() << std::endl;  
    }  
  
    // 清理资源  
    UnmapViewOfFile(lpView);  
    CloseHandle(hMapping);  
    CloseHandle(hFile);  
    return 0;  
}

(7)使用时的注意事项:

  1. FlushViewOfFile函数可能会导致性能开销,因为它涉及磁盘I/O操作。因此,应谨慎使用,避免频繁调用。
  2. 如果视图是由多个进程共享的,那么调用FlushViewOfFile可以确保所有对共享内存的更改都被正确地写回到磁盘文件中。
  3. 在调用FlushViewOfFile之前,应确保对内存映射文件的所有修改都已经完成,以避免数据不一致的情况。
  4. 如果函数失败,应检查GetLastError返回的错误代码以确定失败的原因。可能的错误包括访问违规、句柄无效等。
  5. 在完成内存映射文件的操作后,记得使用UnmapViewOfFile来取消视图映射,并使用CloseHandle关闭文件映射和文件句柄,以避免资源泄漏。

3.17 函数名:GetBinaryType

(1)函数的概述
GetBinaryType函数用于确定文件是否为32位或64位可执行文件(包括DLL和EXE文件),或者是否不是可执行文件(比如其他类型的文件)。

(2)函数所在的动态链接库
GetBinaryType函数位于kernel32.dll动态链接库中。

(3)函数的原型

BOOL GetBinaryType(  
  LPCTSTR lpszFileName,  
  LPDWORD lpBinaryType  
);

(4)各参数及返回值的详细解释

  • lpszFileName:要检查的文件路径字符串。
  • lpBinaryType:一个指向DWORD变量的指针,用于接收文件类型的标识。可能的值有:
  • SCS_32BIT_BINARY:表示32位Windows可执行文件。
  • SCS_64BIT_BINARY:表示64位Windows可执行文件。
  • SCS_DOS_BINARY:表示MS-DOS可执行文件(现已过时,通常不会返回这个值)。
  • SCS_WOW_BINARY:表示在32位Windows上运行的16位Windows可执行文件(现已过时,通常不会返回这个值)。
  • SCS_PIF_BINARY:表示用于运行MS-DOS可执行文件的PIF文件(现已过时,通常不会返回这个值)。
  • SCS_POSIX_BINARY:表示POSIX可执行文件(现已过时,通常不会返回这个值)。
  • SCS_OS216_BINARY:表示16位OS/2可执行文件(现已过时,通常不会返回这个值)。
  • 0 (零):表示文件不是一个可执行文件,或者无法识别。
  • 返回值:
  • 如果函数成功,返回值为非零。
  • 如果函数失败,返回值为零。要获取扩展的错误信息,可以调用GetLastError。

(5)函数的详细作用
GetBinaryType函数用于检测一个指定文件是否为32位或64位的Windows可执行文件,或者其他类型的文件。这对于确定应用程序或动态链接库(DLL)是否与当前操作系统架构兼容非常有用。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* filePath = "C:\\Windows\\System32\\notepad.exe";  
    DWORD binaryType;  
  
    if (GetBinaryTypeA(filePath, &binaryType)) {  
        switch (binaryType) {  
            case SCS_32BIT_BINARY:  
                std::cout << "The file is a 32-bit binary." << std::endl;  
                break;  
            case SCS_64BIT_BINARY:  
                std::cout << "The file is a 64-bit binary." << std::endl;  
                break;  
            default:  
                std::cout << "The file is not a recognized binary type." << std::endl;  
                break;  
        }  
    } else {  
        std::cerr << "GetBinaryType failed with error " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保传入的文件路径是正确的,并且文件存在。
  2. 如果函数失败,应该调用GetLastError来检查错误代码,以确定失败的具体原因。
  3. GetBinaryType函数主要用于可执行文件,对于非可执行文件,可能会返回0(零),表示不是可识别的二进制类型。
  4. 对于网络路径或需要特定访问权限的路径,可能需要确保应用程序有足够的权限来访问文件。
  5. 此函数不支持区分.NET程序集或其他非传统可执行文件格式的二进制类型。

3.18 函数名:GetCompressedFileSize

(1)函数的概述
GetCompressedFileSize函数用于检索指定文件的压缩大小(只读的),如果该文件位于一个使用NTFS文件系统的卷上,且该文件或目录被压缩。

(2)函数所在的动态链接库
GetCompressedFileSize函数位于kernel32.dll动态链接库中。

(3)函数的原型

DWORD GetCompressedFileSize(  
  LPCTSTR lpFileName,  
  LPDWORD lpFileSizeHigh  
);

(4)各参数及返回值的详细解释

  • lpFileName:一个指向要检索压缩文件大小的文件的路径名的字符串指针。
  • lpFileSizeHigh:如果文件大小超过DWORD的最大值(4GB - 1字节),则此参数接收文件大小的高32位。如果这个值为NULL,且文件大小超过DWORD的最大值,函数会失败,并设置错误码为ERROR_ARITHMETIC_OVERFLOW。如果文件大小没有超过DWORD最大值,则此参数可以为NULL。
  • 返回值:
  • 如果函数成功,返回值为文件的压缩大小(低32位),以字节为单位。
  • 如果函数失败,返回值为INVALID_FILE_SIZE,并且可以通过调用GetLastError来获取更多的错误信息。

(5)函数的详细作用
GetCompressedFileSize函数用于确定位于NTFS卷上的文件在压缩后的实际大小。如果文件未被压缩或不在NTFS卷上,则该函数返回文件的实际大小,而不是压缩后的大小。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* filePath = "C:\\path\\to\\compressedfile.txt";  
    DWORD fileSizeLow = 0;  
    DWORD fileSizeHigh = 0;  
    DWORD compressedSize = GetCompressedFileSize(filePath, &fileSizeHigh);  
      
    if (compressedSize == INVALID_FILE_SIZE) {  
        DWORD dwError = GetLastError();  
        std::cerr << "GetCompressedFileSize failed with error " << dwError << std::endl;  
    } else {  
        ULARGE_INTEGER fileSize;  
        fileSize.LowPart = compressedSize;  
        fileSize.HighPart = fileSizeHigh;  
          
        std::cout << "Compressed file size: " << fileSize.QuadPart << " bytes" << std::endl;  
    }  
      
    return 0;  
}

(7)使用时的注意事项

  1. 此函数仅适用于位于NTFS卷上的文件,因为只有NTFS文件系统支持文件级别的压缩。
  2. 如果文件大小可能超过4GB,必须提供一个非空的lpFileSizeHigh参数以避免溢出错误。
  3. 如果函数失败,需要检查GetLastError的返回值来确定失败的原因。
  4. 即使在NTFS文件系统上,如果文件或文件夹没有设置压缩属性,该函数仍然返回文件的实际大小,而不是压缩后的大小。

3.19 函数名:GetCurrentDirectory

(1)函数的概述
GetCurrentDirectory是一个Windows API函数,用于检索当前进程的当前工作目录的完整路径。

(2)函数所在的动态链接库
该函数位于kernel32.dll动态链接库中。

(3)函数的原型

DWORD GetCurrentDirectory(  
  DWORD  nBufferLength,  
  LPTSTR lpBuffer  
);

(4)各参数及返回值的详细解释

  • nBufferLength:指定lpBuffer缓冲区的大小(以字符为单位,包括空字符)。如果此参数设置为0,GetCurrentDirectory将返回所需缓冲区的大小,不包括终止null字符。
  • lpBuffer:指向接收当前目录路径的缓冲区的指针。路径字符串以null结尾,并且其长度(包括终止null字符)必须小于或等于nBufferLength参数指定的值。
  • 返回值:
  • 如果函数成功,返回值是复制到lpBuffer的字符数,不包括终止null字符。
  • 如果nBufferLength太小,无法容纳路径加上终止null字符,函数将失败,返回值是需要的缓冲区大小,包括终止null字符。
  • 如果函数失败,返回值是0。要获取扩展的错误信息,可以调用GetLastError。
  • (5)函数的详细作用
  • GetCurrentDirectory函数用于获取当前进程的工作目录,这是执行文件操作(如打开文件)时的默认目录。获取的工作目录路径被复制到提供的缓冲区中。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
#include <tchar.h>  
  
int main() {  
    TCHAR buffer[MAX_PATH];  
    DWORD dwRet = GetCurrentDirectory(MAX_PATH, buffer);  
    if (dwRet == 0) {  
        std::cerr << "GetCurrentDirectory failed with error " << GetLastError() << std::endl;  
        return 1;  
    }  
    std::wcout << L"Current directory is: " << buffer << std::endl;  
    return 0;  
}

(7)使用时的注意事项

  1. 确保lpBuffer指向的缓冲区足够大,能够存储完整的路径信息以及一个额外的null终止字符。
  2. 如果不确定所需缓冲区大小,可以先调用GetCurrentDirectory函数一次,将nBufferLength设置为0,以获取所需缓冲区的大小,然后分配足够大的缓冲区后再次调用该函数。
  3. GetCurrentDirectory获取的是当前进程的工作目录,不一定是程序所在的目录。如果需要程序所在的目录,需要使用其他方法(如GetModuleFileName获取完整路径,然后提取目录部分)。
  4. 在多线程环境中,不同线程可以更改它们自己的工作目录,这可能会影响到其他使用相对路径的文件操作。因此,在多线程程序中最好使用绝对路径,或者确保所有线程都使用相同的工作目录。

3.20 函数名:GetDiskFreeSpace

(1)函数的概述
GetDiskFreeSpace函数是一个Windows API函数,用于获取指定磁盘分区的可用空间信息。

(2)函数所在的动态链接库
该函数位于kernel32.dll动态链接库中。

(3)函数的原型

BOOL GetDiskFreeSpace(  
  LPCTSTR lpRootPathName,  
  LPDWORD lpSectorsPerCluster,  
  LPDWORD lpBytesPerSector,  
  LPDWORD lpNumberOfFreeClusters,  
  LPDWORD lpTotalNumberOfClusters  
);

(4)各参数及返回值的详细解释

  • lpRootPathName:一个指向以null结尾的字符串,指定要查询的磁盘分区的根路径(例如:"C:\")。
  • lpSectorsPerCluster:一个指向DWORD变量的指针,用于接收每个簇的扇区数。
  • lpBytesPerSector:一个指向DWORD变量的指针,用于接收每个扇区的字节数。
  • lpNumberOfFreeClusters:一个指向DWORD变量的指针,用于接收可用的簇数量。
  • lpTotalNumberOfClusters:一个指向DWORD变量的指针,用于接收分区中的总簇数量。
  • 返回值:如果函数成功,返回值为非零。如果函数失败,返回值为0。要获取扩展的错误信息,可以调用GetLastError。

(5)函数的详细作用
GetDiskFreeSpace函数用于检索关于磁盘分区的信息,包括每个簇的扇区数、每个扇区的字节数、可用的簇数量和分区中的总簇数量。通过这些信息,可以计算出磁盘分区的总大小和可用空间大小。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    DWORD sectorsPerCluster, bytesPerSector, numberOfFreeClusters, totalNumberOfClusters;  
    BOOL result = GetDiskFreeSpace(TEXT("C:\\"), &sectorsPerCluster, &bytesPerSector, &numberOfFreeClusters, &totalNumberOfClusters);  
  
    if (result) {  
        ULARGE_INTEGER totalBytes, freeBytes;  
        totalBytes.QuadPart = static_cast<ULONGLONG>(sectorsPerCluster) * bytesPerSector * totalNumberOfClusters;  
        freeBytes.QuadPart = static_cast<ULONGLONG>(sectorsPerCluster) * bytesPerSector * numberOfFreeClusters;  
          
        std::cout << "Total disk size: " << totalBytes.QuadPart << " bytes" << std::endl;  
        std::cout << "Free disk size: " << freeBytes.QuadPart << " bytes" << std::endl;  
    } else {  
        DWORD error = GetLastError();  
        std::cerr << "GetDiskFreeSpace failed with error code: " << error << std::endl;  
    }  
      
    return 0;  
}

(7)使用时的注意事项

  1. 确保提供的磁盘分区路径是正确的,并且程序有足够的权限去访问该分区信息。
  2. GetDiskFreeSpace函数提供的信息可能不是实时的,因为它可能缓存了某些数据。如果需要更准确的信息,可能需要调用其他更专业的API或使用系统管理工具。
  3. 由于DWORD类型的限制,如果磁盘分区非常大,该函数可能无法正确返回所有的簇数量。在这种情况下,应考虑使用GetDiskFreeSpaceEx函数,它支持更大的磁盘空间,并且可以直接返回以字节为单位的可用空间和总空间大小。

3.21 函数名:GetDiskFreeSpaceEx


(1)函数的概述
GetDiskFreeSpaceEx 是一个Windows API函数,用于检索有关磁盘的可用空间信息,包括磁盘的总容量、可用空间、已用空间以及支持的最大文件大小。

(2)函数所在的动态链接库
这个函数定义在Kernel32.dll动态链接库中。

(3)函数的原型

BOOL GetDiskFreeSpaceEx(  
  LPCTSTR lpRootPathName,  
  PULARGE_INTEGER lpFreeBytesAvailable,  
  PULARGE_INTEGER lpTotalNumberOfBytes,  
  PULARGE_INTEGER lpTotalNumberOfFreeBytes  
);

(4)各参数及返回值的详细解释

  • lpRootPathName:类型:LPCTSTR指向要查询的磁盘根路径的字符串(如 "C:")。可以使用 NULL 来查询当前驱动器。
  • lpFreeBytesAvailable:

类型:PULARGE_INTEGER

指向一个ULARGE_INTEGER结构体的指针,该结构体将接收调用者可以使用的字节数。

  • lpTotalNumberOfBytes:

类型:PULARGE_INTEGER

指向一个ULARGE_INTEGER结构体的指针,该结构体将接收磁盘的总字节数。

  • lpTotalNumberOfFreeBytes:

类型:PULARGE_INTEGER

指向一个ULARGE_INTEGER结构体的指针,该结构体将接收磁盘上所有可用的未分配字节数,包括为系统文件保留的字节数。

  • 返回值:如果函数成功,返回值为非零。如果函数失败,返回值为零。要获取扩展的错误信息,请调用GetLastError。

(5)函数的详细作用
GetDiskFreeSpaceEx函数的主要作用是查询磁盘的容量和可用空间信息。它提供了比GetDiskFreeSpace更精确的信息,尤其是当磁盘容量大于2GB时。此外,它还返回了关于文件系统支持的最大文件大小的信息(尽管在Windows API中,该信息并不总是由这个函数直接返回)。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    ULARGE_INTEGER freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes;  
    if (GetDiskFreeSpaceEx(NULL, &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes)) {  
        std::wcout << L"Total space: " << totalNumberOfBytes.QuadPart / (1024 * 1024) << L" MB" << std::endl;  
        std::wcout << L"Free space: " << freeBytesAvailable.QuadPart / (1024 * 1024) << L" MB" << std::endl;  
    } else {  
        std::cerr << "GetDiskFreeSpaceEx failed with error: " << GetLastError() << std::endl;  
    }  
    return 0;  
}

(7)使用时的注意事项

  1. 确保传递给lpRootPathName的参数是一个有效的磁盘根路径,或者使用NULL来查询当前驱动器。
  2. 在使用ULARGE_INTEGER结构体时,要注意其QuadPart成员,因为它是一个64位整数,可以处理大于2GB的磁盘容量。
  3. 始终检查函数的返回值以确定是否成功执行了查询。如果失败,可以使用GetLastError来获取更详细的错误信息。
  4. 如果在多线程环境中使用此函数,请确保适当地同步对共享资源的访问,以避免潜在的竞争条件。

3.22 函数名:GetDriveType


(1)函数的概述
GetDriveType 是一个Windows API函数,用于确定磁盘驱动器的类型。它返回一个整数值,代表驱动器的类型(如固定硬盘、可移动磁盘、网络驱动器、RAM磁盘等)。

(2)函数所在的动态链接库
GetDriveType 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

UINT GetDriveType(  
  LPCTSTR lpRootPathName  
);

(4)各参数及返回值的详细解释

  • lpRootPathName:

类型:LPCTSTR

一个指向驱动器根目录路径的字符串(例如 "C:")。

  • 返回值:

UINT 类型值,代表驱动器的类型。可能的返回值包括:

DRIVE_UNKNOWN:驱动器类型未知。

DRIVE_NO_ROOT_DIR:路径无效。

DRIVE_REMOVABLE:可移动磁盘。

DRIVE_FIXED:固定磁盘(如硬盘)。

DRIVE_REMOTE:网络驱动器。

DRIVE_CDROM:CD-ROM驱动器。

DRIVE_RAMDISK:RAM磁盘。

(5)函数的详细作用
GetDriveType 函数的作用是确定给定根目录路径所代表的磁盘驱动器的类型。通过返回不同的整数值,函数可以帮助程序根据驱动器类型执行不同的操作,比如决定是否在可移动磁盘上创建临时文件,或者是否从网络驱动器上复制文件等。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    UINT driveType = GetDriveType(TEXT("C:\\"));  
    switch (driveType) {  
        case DRIVE_UNKNOWN:  
            std::cout << "Unknown drive type." << std::endl;  
            break;  
        case DRIVE_NO_ROOT_DIR:  
            std::cout << "Invalid root path." << std::endl;  
            break;  
        case DRIVE_REMOVABLE:  
            std::cout << "Removable disk." << std::endl;  
            break;  
        case DRIVE_FIXED:  
            std::cout << "Fixed disk." << std::endl;  
            break;  
        case DRIVE_REMOTE:  
            std::cout << "Network drive." << std::endl;  
            break;  
        case DRIVE_CDROM:  
            std::cout << "CD-ROM drive." << std::endl;  
            break;  
        case DRIVE_RAMDISK:  
            std::cout << "RAM disk." << std::endl;  
            break;  
        default:  
            std::cout << "Unsupported drive type." << std::endl;  
    }  
    return 0;  
}

(7)使用时的注意事项

  1. 确保传递给 lpRootPathName 的参数是一个有效的驱动器根目录路径。
  2. 函数返回的是驱动器类型,而不是驱动器是否准备好或是否存在。如果驱动器不存在或无法访问,GetDriveType 可能返回 DRIVE_UNKNOWN 或 DRIVE_NO_ROOT_DIR。
  3. 如果在多线程环境中使用此函数,请确保适当地同步对共享资源的访问,以避免潜在的竞争条件。
  4. 如果程序需要在处理网络驱动器时考虑到网络延迟或断开连接的情况,可能需要额外的逻辑来确保程序能够优雅地处理这些情况。
  5. 如果程序需要处理多种不同的驱动器类型,并可能需要针对每种类型执行不同的操作,请确保程序能够正确地解析 GetDriveType 的返回值,并据此执行适当的操作。

3.23 函数名:GetFileAttributes

(1)函数的概述

GetFileAttributes 是一个Windows API函数,用于获取一个文件或目录的属性。这些属性可以包括文件是否为只读、隐藏、系统文件,以及它是否是一个目录等。

(2)函数所在的动态链接库

GetFileAttributes 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetFileAttributes(  
  LPCTSTR lpFileName  
);

(4)各参数及返回值的详细解释

  • lpFileName(输入参数):

类型:LPCTSTR(长指针到常量TCHAR字符串)

描述:要获取其属性的文件或目录的名称。

  • 返回值:

类型:DWORD(32位无符号整数)

描述:如果函数成功,返回值是一个包含文件属性的位掩码。如果函数失败,返回值是 INVALID_FILE_ATTRIBUTES。

常见的文件属性值包括:

FILE_ATTRIBUTE_READONLY:文件是只读的。

FILE_ATTRIBUTE_HIDDEN:文件是隐藏的。

FILE_ATTRIBUTE_SYSTEM:文件是系统文件。

FILE_ATTRIBUTE_DIRECTORY:路径是一个目录。

FILE_ATTRIBUTE_ARCHIVE:文件自上次备份以来已经更改。

等等。

(5)函数的详细作用

GetFileAttributes 函数的作用是查询指定文件或目录的属性。这些属性可以帮助程序确定如何与文件或目录交互,例如,一个只读文件可能不应被修改,而一个隐藏文件可能不应该在用户界面上显示。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 文件路径  
    const char* filePath = "C:\\example\\test.txt";  
  
    // 获取文件属性  
    DWORD fileAttributes = GetFileAttributesA(filePath);  
  
    // 检查函数是否成功  
    if (fileAttributes == INVALID_FILE_ATTRIBUTES) {  
        std::cerr << "GetFileAttributes failed for: " << filePath << std::endl;  
        return 1;  
    }  
  
    // 输出文件属性  
    if (fileAttributes & FILE_ATTRIBUTE_READONLY) {  
        std::cout << "The file is read-only." << std::endl;  
    }  
    if (fileAttributes & FILE_ATTRIBUTE_HIDDEN) {  
        std::cout << "The file is hidden." << std::endl;  
    }  
    if (fileAttributes & FILE_ATTRIBUTE_SYSTEM) {  
        std::cout << "The file is a system file." << std::endl;  
    }  
    if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {  
        std::cout << "The file path is a directory." << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 调用 GetFileAttributes 时,需要确保指定的文件或目录路径存在且可访问。
  2. 如果文件或目录不存在,或者由于某种原因(如权限不足)无法访问,函数将返回 INVALID_FILE_ATTRIBUTES。
  3. 返回值是一个位掩码,这意味着可以同时设置多个属性。因此,在检查特定属性时,应使用按位与(&)操作符。
  4. 如果程序需要在多用户环境中运行,并且需要访问其他用户的文件,请确保程序具有适当的权限。
  5. 在处理文件路径时,请确保正确处理路径中的空格和特殊字符,以避免潜在的安全风险。
  6. 对于宽字符字符串(Unicode),应使用 GetFileAttributesW 函数,而不是 GetFileAttributesA。如果文件路径是硬编码的,或者已知为ANSI字符集,则可以使用 GetFileAttributesA。在C++中,可以使用宽字符串字面量(例如 L"path\\to\\file")和 std::wstring 来与 GetFileAttributesW 一起使用。

3.24 函数名:GetFileInformationByHandle

(1)函数的概述

GetFileInformationByHandle 是一个Windows API函数,用于检索与文件或目录句柄关联的信息。这些信息包括文件的大小、创建时间、最后访问时间、最后写入时间以及安全标识符等信息。

(2)函数所在的动态链接库

GetFileInformationByHandle 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL GetFileInformationByHandle(  
  HANDLE     hFile,  
  LPBY_HANDLE_FILE_INFORMATION lpFileInformation  
);

(4)各参数及返回值的详细解释

  • hFile(输入参数):

类型:HANDLE

描述:一个已打开的文件或目录的句柄。这个句柄通常是通过 CreateFile 或 CreateFileEx 函数获取的。

  • lpFileInformation(输出参数):

类型:LPBY_HANDLE_FILE_INFORMATION(指向BY_HANDLE_FILE_INFORMATION结构的指针)

描述:指向一个接收文件信息的缓冲区的指针。调用此函数后,这个结构会被填充有关文件或目录的信息。

  • 返回值:

类型:BOOL

描述:如果函数成功,返回值是非零。如果函数失败,返回值是零。要获取扩展的错误信息,可以调用 GetLastError。

(5)函数的详细作用

GetFileInformationByHandle 函数用于检索与给定文件或目录句柄相关联的详细信息。这些信息通常包括文件的大小、文件的创建时间、最后访问时间、最后写入时间以及文件的属性(如只读、隐藏、系统等)。这个函数在需要获取文件或目录的详细信息时非常有用,而不需要直接操作文件路径。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFileA(  
        "C:\\example\\test.txt", // 文件路径  
        GENERIC_READ,           // 访问权限  
        FILE_SHARE_READ,        // 共享模式  
        NULL,                   // 安全描述符  
        OPEN_EXISTING,          // 如何创建  
        FILE_ATTRIBUTE_NORMAL,   // 文件属性  
        NULL                    // 模板文件句柄  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed." << std::endl;  
        return 1;  
    }  
  
    BY_HANDLE_FILE_INFORMATION fileInfo;  
    if (!GetFileInformationByHandle(hFile, &fileInfo)) {  
        std::cerr << "GetFileInformationByHandle failed." << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    // 打印文件大小  
    std::cout << "File size: " << fileInfo.nFileSizeHigh * (MAXDWORD + 1) + fileInfo.nFileSizeLow << " bytes" << std::endl;  
  
    // ... 可以打印其他信息  
  
    CloseHandle(hFile);  
    return 0;  
}

(7)使用时的注意事项

  • 确保在调用 GetFileInformationByHandle 之前,文件或目录句柄是有效的,并且已经通过 CreateFile 或其他相关函数打开。
  • 在调用 GetFileInformationByHandle 后,务必检查返回值以确保函数成功执行。如果函数失败,可以调用 GetLastError 获取扩展的错误信息。
  • 句柄在使用完毕后应该使用 CloseHandle 函数关闭,以释放系统资源。
  • 在多线程环境中,需要注意对句柄的同步访问,以避免竞态条件。
  • 在处理文件路径时,应确保正确处理路径中的空格和特殊字符,并遵循Windows命名约定。

3.25 函数名:GetFileSize

(1)函数的概述

GetFileSize 是一个Windows API函数,用于检索指定文件的大小,以字节为单位。它基于文件的句柄来获取文件大小,而不是直接基于文件路径。

(2)函数所在的动态链接库

GetFileSize 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetFileSize(  
  HANDLE hFile,  
  LPDWORD lpFileSizeHigh  
);

(4)各参数及返回值的详细解释

  • hFile(输入参数):

类型:HANDLE

描述:一个已打开文件的句柄。此句柄通常由 CreateFile、CreateFileEx 或其他相关文件创建函数返回。

  • lpFileSizeHigh(输出参数):

类型:LPDWORD(指向DWORD的指针)

描述:指向一个变量的指针,该变量接收文件大小的高32位。如果文件大小小于MAXDWORD(即小于4GB),则此值通常为零。

  • 返回值:

类型:DWORD

描述:返回文件大小的低32位。如果函数失败,返回值是 INVALID_FILE_SIZE(即 0xFFFFFFFF)。

(5)函数的详细作用

GetFileSize 函数用于检索由指定句柄引用的文件的大小。这个函数对于需要了解文件大小以便进行进一步处理(如读取、写入或内存分配)的应用程序非常有用。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFileA(  
        "C:\\example\\test.txt",  // 文件路径  
        GENERIC_READ,             // 访问权限  
        FILE_SHARE_READ,          // 共享模式  
        NULL,                     // 安全描述符  
        OPEN_EXISTING,            // 如何创建  
        FILE_ATTRIBUTE_NORMAL,     // 文件属性  
        NULL                      // 模板文件句柄  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed." << std::endl;  
        return 1;  
    }  
  
    DWORD dwSizeLow = 0;  
    DWORD dwSizeHigh = 0;  
    dwSizeLow = GetFileSize(hFile, &dwSizeHigh);  
  
    if (dwSizeLow == INVALID_FILE_SIZE) {  
        std::cerr << "GetFileSize failed." << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    // 计算文件总大小(可能超过4GB)  
    ULARGE_INTEGER fileSize;  
    fileSize.LowPart = dwSizeLow;  
    fileSize.HighPart = dwSizeHigh;  
    std::cout << "File size: " << fileSize.QuadPart << " bytes" << std::endl;  
  
    CloseHandle(hFile);  
    return 0;  
}

(7)使用时的注意事项

  1. 确保在调用 GetFileSize 之前,文件句柄是有效的,并且已经通过 CreateFile 或其他相关函数打开。
  2. 如果文件大小可能超过4GB,请确保使用 ULARGE_INTEGER 类型的变量来存储完整的文件大小。
  3. 在调用 GetFileSize 后,务必检查返回值以确保函数成功执行。如果函数失败,可以调用 GetLastError 获取扩展的错误信息。
  4. 句柄在使用完毕后应该使用 CloseHandle 函数关闭,以释放系统资源。
  5. 在多线程环境中,需要注意对句柄的同步访问,以避免竞态条件。
  6. 在处理文件路径时,应确保正确处理路径中的空格和特殊字符,并遵循Windows命名约定。
     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/593061.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024抖音直播带货-直播间拆解:抖店运营从入门到精通(56节课)

起号原理方式以及节点处理 类目的选择选品思路 付费流量投放原理 直播间进阶玩法 课程内容 直播间搭建标准自然起号(0-1)原理 方式 以及节点处理 老号重启(0-1)原理 方式 以及节点处理 账号在线人数稳定 原理 方式 以及节点处理 账号销售额放大 原理 方式 以及节点处理…

ubuntu20配置深度学习环境

目录 系统环境安装anaconda文件的安装anaconda环境配置anaconda换中科大源常用的anaconda命令 安装显卡驱动安装CUDA下载cudnn安装pytorch更换conda源选择对应的pytorch版本进行安装 系统环境 ubuntu20&#xff0c;安装了ros noetic。 参考博客主要有&#xff1a; https://g…

【Trick】conda安装python依赖时出现429 Client Error

起因 我在根据yml文件安装依赖和创建虚拟环境时&#xff0c;出现报错&#xff0c;主要报错信息为以下两点&#xff1a; 【1】Collecting package metadata (repodata.json): failed 【2】requests.exceptions.HTTPError: 429 Client Error: Too Many Requests for url: https…

Git在无法访问github的访问方法

Git无法下载github上的源代码 代理的情况 问题&#xff1a;Failed to connect to github.com port 443 after 21100 ms: Couldnt connect to server 提示我们需要为Git单独配置代理。 查看我们的代理端口  为git 设置全局代理 git config --global http.proxy 127.0.0.1:&l…

【LeetCode刷题记录】简单篇-104-二叉树的最大深度

【题目描述】 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 【测试用例】 示例1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例2&#xff1a; 输入&#…

颜值高的浏览器 ARC

可以使用 chrome 的插件&#xff0c;和书签&#xff0c;现在可以下载&#xff0c;别的不说这个ui 的颜值是可以的, 而且很丝滑

思考题 —— Windows 登录密码

1.windows登录的明文密码&#xff0c;存储过程是怎么样的&#xff1f;密文存放在哪个文件下&#xff1f;该文件是否可以打开&#xff0c;并且查看到密文&#xff1f; 系统通过保存密码的哈希值来确保安全性&#xff0c;进行加密存储的方法通常为NTLM或Kerberos身份认证协议。该…

SFOS1:开发环境搭建

一、简介 最近在学习sailfish os的应用开发&#xff0c;主要内容是QmlPython。所以&#xff0c;在开发之前需要对开发环境&#xff08;virtualBox官方SDKcmake编译器python&#xff09;进行搭建。值得注意的是&#xff0c;我的开发环境是ubuntu22.04。如果是windows可能大同小异…

Codeforces Round 943 (Div. 3 ABCDEFG1G2题) 视频讲解

A. Maximize? Problem Statement You are given an integer x x x. Your task is to find any integer y y y ( 1 ≤ y < x ) (1\le y<x) (1≤y<x) such that gcd ⁡ ( x , y ) y \gcd(x,y)y gcd(x,y)y is maximum possible. Note that if there is more tha…

Webshell绕过技巧分析之-base64/HEX/Reverse/Html/Inflate/Rot13

在网络安全运营&#xff0c;护网HVV&#xff0c;重保等活动的过程中&#xff0c;webshell是一个无法绕过的话题。通常出现的webshell都不是以明文的形式出现&#xff0c;而是针对webshell关键的内容进行混淆&#xff0c;编码来绕过网络安全产品&#xff08;IDS&#xff0c;WAF&…

Linux USB转串口设备路径的查找方法

1、USB转串口设备 USB转串口设备是在嵌入式软件开发过程中经常要使用的&#xff0c;常常用于对接各种各样的串口设备。如果一台linux主机上使用多个usb转串口设备时&#xff0c;应用程序中就需要知道自己操作的是哪个串口设备。串口设备在系统上电时&#xff0c;由于驱动加载的…

短剧在线搜索表格-送模板

短剧在线搜索表格-附模板 介绍电脑界面手机界面送附加功能&#xff1a;反馈缺失短剧送&#xff1a;资源更新源头获取 介绍 你好&#xff01; 这是你第一次使用 金山在线文档 所生成的短剧搜索表格&#xff0c;支持批量导入自己转存的短剧名字和链接&#xff0c;实现在线搜索&a…

Kotlin基础知识总结(三万字超详细)

1、条件语句 &#xff08;1&#xff09;if条件 if条件表达式&#xff0c;每一个分支最后一条语句就是该分支的返回值。适用于每个分支返回值类型一致这种情况。 fun getDegree(score: Int): String{val result: String if(score 100){"非常优秀"}else if(score …

Docker使用进阶篇

文章目录 1 前言2 使用Docker安装常用镜像示例2.1 Docker安装RabbitMQ2.2 Docker安装Nacos2.3 Docker安装xxl-job&#xff08;推荐该方式构建&#xff09;2.4 Docker安装redis2.5 Docker安装mysql 1 前言 上一篇介绍了Docker的基础概念&#xff0c;带你 入门Docker&#xff0c…

菜鸡学习netty源码(四)—— EventLoopGroup

1.概述 我们前面进行过分析,channel为netty网络操作的抽象类,EventLoop负责处理注册到其上的Channel处理的I/O事件;EventLoopGroup是一个EventLoop的分组,它可以获取到一个或者多个的EventLoop对象。 2.类关系图 NioEventLoopGroup的类继承图,蓝色部分为对应的java类,绿…

当管道运算符遇上无限可能:探索数据流的奇妙之旅

文章目录 序言目的进程间通信的理解进程间通信的发展历史管道创建验证管道的大小管道的4种情况管道的5种特征 序言 通过该命令计算了在当前路径下一共有多少个文件夹的任务 进程虽然有独立性,但是进程并不孤僻,他们之间也会相互进行协作共同完成一件事 这个前提是他们之间的信…

Java如何获取当前日期和时间?

Java如何获取当前日期和时间&#xff1f; 本文将为您介绍 Java 中关于日期和时间获取的方法&#xff0c;以及介绍 Java 8 中获取日期和时间的全新API。 1、 System.currentTimeMillis() 获取标准时间可以使用 System.currentTimeMillis() 方法来获取&#xff0c;此方法优势是…

Flutter笔记:Widgets Easier组件库(12)使用消息吐丝(Notify Toasts)

Flutter笔记 Widgets Easier组件库&#xff08;12&#xff09;使用消息吐丝&#xff08;Notify Toasts&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 29114848416…

Linux(openEuler、CentOS8)基于chrony企业内网NTP服务器搭建实验

一、知识点 chrony 是由 守护进程 chronyd 以及 命令行工具 chronyc 组成的 chronyd 在后台静默运行并通过 123 端口与时间服务器定时同步时间&#xff0c;默认的配置文件是 /etc/chrony.conf chronyc 通过 323 端口与 chronyd 交互&#xff0c;可监控 chronyd 的性能并在运…

单例、工厂、策略、装饰器设计模式

1. 单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a; 单例模式是一种常用的设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这种模式的特点是类自己负责保存其唯一的实例&#xff0c;并控制其实例化过程。单例模式广泛应用…
最新文章