检查filesize而不在c ++中打开文件?

use*_*566 28 c++ windows winapi

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

Dav*_*nan 44

您应该拨打GetFileSizeEx哪个比旧版更容易使用GetFileSize.您需要通过调用打开文件,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;
}
Run Code Online (Sandbox Code Playgroud)

还有其他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;
}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用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;
} 
Run Code Online (Sandbox Code Playgroud)

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

  • @Alexis阅读雷蒙德的文章,了解细节.元数据包含大小的副本,但它可能已过期.真实大小在文件中.http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx (2认同)

Cod*_*gry 28

我也生活在担心打开文件所付出的代价并关闭它以获得它的大小.并决定询问性能计数器 ^并查看操作的实际成本.

这是使用三种方法在同一文件上执行1文件大小查询所花费的周期数.测试了2个文件:150 MB和1.5 GB.得到+/- 10%的波动,因此它们似乎不受实际文件大小的影响.(显然这取决于CPU,但它给你一个很好的有利位置)

  • 190个循环 - ,,CreateFileGetFileSizeExCloseHandle
  • 40个周期 -GetFileAttributesEx
  • 150个周期 - FindFirstFile,FindClose

使用代码的GIST ^ 可在此处获得.

正如我们从这个高度科学的测试中看到的那样,最慢的实际上是文件开启者.第二慢的是文件查找器,而获胜者是属性读取器.现在,在可靠性方面,CreateFile应该优先于其他2.但我仍然不喜欢打开文件的概念只是为了阅读它的大小...除非我做大小关键的东西,我会去的属性.

PS:当我有时间时,我将尝试读取已打开并正在写入的文件的大小.但现在不是......

  • 关于您的 **PS**:看起来 GetFileAttributesEx() 实际上确实返回了正确的文件大小,而文件仍在由另一个进程更新,这使其成为最快(正确的文件大小)选择。如果它只有最后一次文件更改时间(不要与上次写入时间混淆),那么这个功能就完美了! (2认同)

RRU*_*RUZ 9

使用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 %u\n"), FileSize);
      FindClose(hFind);
   }
   return 0;

}
Run Code Online (Sandbox Code Playgroud)

  • 使用“ULARGE_INTEGER”而不是手动调整“ULONGLONG”位,例如:“ULARGE_INTEGER ul;” ul.LowPart = FindFileData.nFileSizeLow; ul.HighPart = FindFileData.nFileSizeHigh; ULONGLONG 文件大小 = ul.QuadPart;`。另外,“%u”在 Windows 上需要 32 位“unsigned int”,对于 64 位整数,您需要使用“%Lu”。 (2认同)
  • 我相信FindFirstFile会检索目录条目中记录的文件大小.请注意,在某些情况下,这可能不准确,例如,如果文件是硬链接的,并且是通过其他硬链接修改的,或者另一个应用程序打开文件并对其进行了修改.请参阅http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx (2认同)

Dav*_*ing 5

从 C++17 开始,file_size作为标准库的一部分。(然后实施者可以决定如何有效地完成它!)


Arm*_*yan 0

GetFileSize函数怎么样?

  • 这需要打开文件,OP 表示这是不可取的。 (3认同)
  • @Remy 不是根据雷蒙德:http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx 另外,如果您不使用 &lt;at&gt;name 那么就不会一条通知,这样你就只能自言自语了! (3认同)