it-swarm.com.de

Überprüfen Sie die Dateigröße, ohne die Datei in C++ zu öffnen.

Ich versuche, die Dateigröße einer großen Datei (12 GB +) zu ermitteln, und ich möchte die Datei nicht öffnen, um dies zu tun, da ich davon ausgehe, dass dies eine Menge Ressourcen kosten würde. Gibt es eine gute API, um dies zu tun? Ich bin in einer Windows-Umgebung. 

26
user1167566

Sie sollten GetFileSizeEx aufrufen, was einfacher zu verwenden ist als die ältere GetFileSize . Sie müssen die Datei öffnen, indem Sie CreateFile aufrufen. Dies ist jedoch ein billiger Vorgang. Ihre Annahme, dass das Öffnen einer Datei teuer ist, auch eine 12-GB-Datei, ist falsch.

Sie können die folgende Funktion verwenden, um die Aufgabe zu erledigen:

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

Es gibt andere API-Aufrufe, die Ihnen die Dateigröße zurückgeben, ohne dass Sie ein Dateihandle erstellen müssen, insbesondere GetFileAttributesEx . Es ist jedoch absolut plausibel, dass diese Funktion die Datei nur hinter den Kulissen öffnet.

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

Wenn Sie mit Visual Studio kompilieren und den Aufruf von Win32-APIs vermeiden möchten, können Sie _wstat64 verwenden.

Hier ist eine _wstat64-basierte Version der Funktion:

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

Wenn Leistung jemals ein Problem für Sie geworden ist, sollten Sie die verschiedenen Optionen auf allen Plattformen, auf die Sie abzielen, zeitlich festlegen, um eine Entscheidung zu treffen. Gehen Sie nicht davon aus, dass die APIs, für die Sie nicht CreateFile aufrufen müssen, schneller sind. Sie könnten es sein, aber Sie werden es nicht wissen, bis Sie es festgelegt haben.

42
David Heffernan

Ich habe auch mit der Angst gelebt, den Preis dafür zu zahlen, eine Datei zu öffnen und zu schließen, nur um ihre Größe zu ermitteln. Leistungsindikator ^ und sehen, wie teuer die Operationen wirklich sind.

Dies ist die Anzahl der Zyklen, die erforderlich waren, um mit den drei Methoden 1 Dateigrößenabfrage für dieselbe Datei auszuführen. Getestet mit 2 Dateien: 150 MB und 1,5 GB. Schwankungen von +/- 10% scheinen daher nicht von der tatsächlichen Dateigröße betroffen zu sein. (Dies hängt natürlich von der CPU ab, bietet Ihnen jedoch einen guten Blickwinkel.)

  • 190 Zyklen - CreateFile, GetFileSizeEx, CloseHandle
  • 40 Zyklen - GetFileAttributesEx
  • 150 Zyklen - FindFirstFile, FindClose

Das Gist mit dem verwendeten Code ^ ist hier verfügbar .

Wie wir aus diesem sehr wissenschaftlichen :) Test ersehen können, ist der Dateiöffner tatsächlich der langsamste. Der zweitlängste ist der Datei-Finder, während der Gewinner der Attribut-Reader ist. Nun, in Bezug auf die Zuverlässigkeit sollte CreateFile den anderen 2 vorgezogen werden. Aber ich mag das Konzept des Öffnens eines Datei, nur um ihre Größe zu lesen ... Wenn ich keine größenkritischen Dinge mache, gehe ich zu den Attributen .

PS: Wenn ich Zeit habe, werde ich versuchen, die Größe von Dateien zu lesen, die geöffnet sind und gerade geschrieben werden zu. Aber gerade nicht ...

28
CodeAngry

Eine weitere Option mit der Funktion 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
RRUZ

Was ist mit der Funktion GetFileSize ?

1
Armen Tsirunyan

Ab C++ 17 gibt es file_size als Teil der Standardbibliothek. (Dann kann der Implementierer entscheiden, wie er effizient arbeiten soll!)

0
Davis Herring