Проверить размер файла без открытия файла в C++?

Я пытаюсь получить размер файла большого размера (12gb+) и не хочу открывать файл, чтобы сделать это, так как предполагаю, что это съест много ресурсов. Есть ли какой-нибудь хороший API, с помощью которого можно это сделать? Я работаю в среде Windows.

28
задан Ajay 6 June 2019 в 09:59
поделиться

4 ответа

Вы должны позвонить GetFileSizeEx , который проще в использовании, чем более старый GetFileSize . Вам нужно будет открыть файл по телефону CreateFile, но это дешевая операция. Ваше предположение, что открытие файла дорого, даже файл размером 12 ГБ, неверно.

Вы можете использовать следующую функцию для выполнения работы:

__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;
} 

Если производительность когда-либо становилась для вас проблемой, то вам следует рассчитать различные варианты на всех платформах, на которые вы ориентируетесь. Чтобы прийти к решению. Не думайте, что API, которые не требуют вызова CreateFile, будут быстрее. Они могут быть, но вы не узнаете, пока не рассчитаете время.

44
ответ дан 28 November 2019 в 02:30
поделиться

Я также жил со страхом за цену, заплаченную за открытие файла и его закрытие, чтобы получить его размер. И решил спросить у счетчика производительности ^ и посмотреть, насколько дорогими на самом деле являются операции.

Это количество циклов, которое потребовалось для выполнения 1 запроса размера файла в одном и том же файле тремя способами. Проверено на 2 файлах: 150 МБ и 1,5 ГБ. Получил колебания +/- 10%, поэтому они не зависят от размера файла. (очевидно, это зависит от процессора, но дает хороший обзор)

  • 190 циклов - CreateFile, GetFileSizeEx, CloseHandle
  • 40 циклов - GetFileAttributesEx
  • 150 циклов - FindFirstFile, FindClose

GIST с используемым кодом ^ доступен здесь .

Как мы можем видеть из этого очень научного :) теста , самый медленный на самом деле - средство для открытия файлов. 2-й самый медленный - искатель файлов, а победитель - читатель атрибутов. Теперь, с точки зрения надежности, CreateFile следует отдать предпочтение перед другими 2. Но мне все еще не нравится концепция открытия файла только для того, чтобы прочитать его размер ... Если я не занимаюсь вопросами, определяющими размер, я перейду к Атрибутам .

PS : Когда у меня будет время, я попытаюсь прочитать размеры открываемых файлов и пишу в них. Но не сейчас ...

28
ответ дан 28 November 2019 в 02:30
поделиться

Еще один вариант использования функции 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;

}
.
9
ответ дан 28 November 2019 в 02:30
поделиться

Начиная с C ++ 17, есть file_size как часть стандартной библиотеки. (Тогда разработчик решает, как это сделать эффективно!)

2
ответ дан 28 November 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: