在不使用C++打开文件的情况下检查文件大小

Check the file-size without opening file in C++?

本文关键字:文件 情况下 检查 文件大小 C++      更新时间:2023-10-16

我正在尝试获取一个大文件(12gb+)的文件大小,但我不想打开该文件,因为我认为这会占用大量资源。有什么好的API可以这样做吗?我在Windows环境中。

您应该调用比旧GetFileSize更易于使用的GetFileSizeEx。您需要通过调用CreateFile来打开文件,但这是一个廉价的操作。你认为打开一个文件很昂贵,即使是12GB的文件,也是错误的。

您可以使用以下功能来完成任务:

__int64 FileSize(const wchar_t* name)
{
    HANDLE hFile = CreateFile(name, GENERIC_READ, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile==INVALID_HANDLE_VALUE)
        return -1; // error condition, could call GetLastError to find out more
    LARGE_INTEGER size;
    if (!GetFileSizeEx(hFile, &size))
    {
        CloseHandle(hFile);
        return -1; // error condition, could call GetLastError to find out more
    }
    CloseHandle(hFile);
    return size.QuadPart;
}

还有其他API调用将返回文件大小,而无需创建文件句柄,特别是GetFileAttributesEx。然而,这个函数只是在幕后打开文件,这是完全合理的。

__int64 FileSize(const wchar_t* name)
{
    WIN32_FILE_ATTRIBUTE_DATA fad;
    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
        return -1; // error condition, could call GetLastError to find out more
    LARGE_INTEGER size;
    size.HighPart = fad.nFileSizeHigh;
    size.LowPart = fad.nFileSizeLow;
    return size.QuadPart;
}

如果使用Visual Studio进行编译,并且希望避免调用Win32 API,则可以使用_wstat64

以下是基于_wstat64的函数版本:

__int64 FileSize(const wchar_t* name)
{
    __stat64 buf;
    if (_wstat64(name, &buf) != 0)
        return -1; // error, could use errno to find out more
    return buf.st_size;
} 

如果性能曾经成为您的一个问题,那么您应该对所有目标平台上的各种选项进行计时,以便做出决定。不要以为不需要调用CreateFile的API会更快。它们可能是,但在计时之前你不会知道。

我也生活在打开文件并关闭文件以获取其大小所付出的代价的恐惧中并决定询问性能计数器^,看看这些操作的成本到底有多高。

这是使用三种方法对同一文件执行1个文件大小查询所花费的周期数在2个文件上进行了测试:150 MB和1.5 GB。有+/-10%的波动,所以它们似乎不受实际文件大小的影响(显然这取决于CPU,但它为您提供了一个很好的优势)

  • 190次循环-CreateFileGetFileSizeExCloseHandle
  • 40次循环-GetFileAttributesEx
  • 150次循环-FindFirstFileFindClose

此处提供带有所用代码的GIST^

正如我们从这个高度科学化的测试中看到的:)测试,最慢的实际上是文件打开程序。排名第二的是文件查找器,而排名第一的是属性读取器现在,就可靠性而言,CreateFile应该比其他2更受欢迎。但我仍然不喜欢打开文件只是为了读取其大小的概念。。。除非我在做尺寸关键的事情,否则我会选择属性

PS当我有时间的时候,我会尝试读取打开并正在写入的文件的大小。但现在不行

使用FindFirstFile函数的另一个选项

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;
   LPCTSTR  lpFileName = L"C:\Foo\Bar.ext";
   hFind = FindFirstFile(lpFileName , &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("File not found (%d)n", GetLastError());
      return -1;
   } 
   else 
   {
      ULONGLONG FileSize = FindFileData.nFileSizeHigh;
      FileSize <<= sizeof( FindFileData.nFileSizeHigh ) * 8; 
      FileSize |= FindFileData.nFileSizeLow;
      _tprintf (TEXT("file size is %un"), FileSize);
      FindClose(hFind);
   }
   return 0;
}

与C++17一样,file_size是标准库的一部分。(然后实现者可以决定如何高效地完成它!)

GetFileSize函数怎么样?

相关文章: