Sto cercando di ottenere il file di un file di grandi dimensioni (12 gb +) e non voglio aprire il file per farlo, dato che presumo questo mangerebbe un sacco di risorse. C'è qualche buona API con cui farlo? Sono in un ambiente Windows.Controllare i file senza aprire il file in C++?
risposta
Che dire della funzione GetFileSize?
È necessario chiamare GetFileSizeEx
che è più facile da usare rispetto al precedente GetFileSize
. Avrai bisogno di aprire il file chiamando lo CreateFile
ma è un'operazione a basso costo. La tua ipotesi che l'apertura di un file sia costosa, anche un file da 12 GB, è falsa.
è possibile utilizzare la seguente funzione per ottenere il lavoro fatto:
__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;
}
Non ci sono altre chiamate API che restituirà la dimensione del file, senza costringere a creare un handle file, in particolare GetFileAttributesEx
. Tuttavia, è perfettamente plausibile che questa funzione aprirà il file dietro le quinte.
__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;
}
Se si compila con Visual Studio e si vuole evitare di chiamare API Win32 è possibile utilizzare _wstat64
.
Ecco una versione _wstat64
base della funzione:
__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;
}
Se le prestazioni mai diventato un problema per voi, allora si dovrebbe cronometrare le varie opzioni su tutte le piattaforme che come bersaglio al fine di raggiungere una decisione. Non dare per scontato che le API che non richiedono di chiamare CreateFile
saranno più veloci. Potrebbero esserlo ma non lo saprai finché non lo avrai cronometrato.
Naturalmente, '' CreateFile() 'può essere piuttosto lento se si sta aprendo il file su supporti lenti] (http://blogs.msdn.com/b/larryosterman/archive/2004/05/24/140396. aspx) come unità di rete, ma la lentezza sarebbe dovuta alle latenze di accesso allo storage e non a causa del fatto che il file è enorme. –
@Insilico O unità nastro! Ma credo che l'apertura del file sia l'unico modo per trovare la dimensione del file, almeno su Windows. –
@DavidHeffernan: No! La dimensione del file è nell'intestazione e quindi nella directory. FindFirstFile() come mostrato di seguito leggerà queste informazioni senza dover aprire il file. –
Un'altra opzione utilizzando la funzione di 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;
}
Utilizzare 'ULARGE_INTEGER' invece di girare manualmente i bit' ULONGLONG', ad es .: 'ULARGE_INTEGER ul; ul.LowPart = FindFileData.nFileSizeLow; ul.HighPart = FindFileData.nFileSizeHigh; ULONGLONG FileSize = ul.QuadPart; '. Inoltre, '% u' si aspetta un' unsigned int' a 32 bit su Windows, è necessario usare '% Lu' invece per un numero intero a 64 bit. –
Credo che FindFirstFile recuperi le dimensioni del file come registrato nella voce della directory. Si noti che in alcune circostanze ciò potrebbe non essere accurato, ad es. Se il file è hard link ed è stato modificato tramite un diverso hard link, o se un'altra applicazione ha il file aperto e lo ha modificato. Vedi http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx –
Presumibilmente il problema a cui Harry fa riferimento è il motivo per cui la RTL Delphi ha smesso di utilizzare FindFirstFile nella sua funzione sys della dimensione del file. –
Ho anche vissuto con la paura del prezzo pagato per l'apertura di un file e la chiusura solo per ottenere la sua dimensione. E ha deciso di chiedere allo performance counter^ e vedere quanto costose siano davvero le operazioni.
Questo è il numero di cicli necessari per eseguire 1 query di dimensioni file sullo stesso file con i tre metodi. Testato su 2 file: 150 MB e 1,5 GB. Hai fluttuazioni del +/- 10% in modo che non sembrino influenzate dalle dimensioni effettive del file. (ovviamente questo dipende da CPU ma ti dà un buon punto di osservazione)
- 190 cicli -
CreateFile
,GetFileSizeEx
,CloseHandle
- 40 cicli -
GetFileAttributesEx
- 150 cicli -
FindFirstFile
,FindClose
The GIST with the code used^è disponibile qui.
Come possiamo vedere da questo test altamente scientifico :), il più lento è in realtà l'apri file. Il secondo più lento è il file finder mentre il vincitore è il lettore degli attributi. Ora, in termini di affidabilità, l'CreateFile
deve essere preferito rispetto all'altro 2. Ma non mi piace ancora il concetto di aprire un file solo per leggere le sue dimensioni ... A meno che non stia facendo cose di dimensioni critiche, io Andiamo per gli attributi .
PS: Quando avrò tempo cercherò di leggere le dimensioni dei file aperti e in cui sto scrivendo. Ma non adesso ...
A partire da C++ 17, c'è il numero file_size come parte della libreria standard. (Quindi l'implementatore deve decidere come farlo in modo efficiente!)
- 1. Impossibile aprire il file in Excel C#
- 2. Aprire il file senza (davvero) bloccarlo?
- 3. come controllare il file aperto senza lsof
- 4. Controllare se il file esiste senza creare lo
- 5. Un modo migliore per aprire i file HDF5 in C++
- 6. Aprire il file ReadOnly
- 7. Aprire il file con il suo percorso completo in C++
- 8. Devo controllare i file * .mo?
- 9. Che cos'è aprire un file in C?
- 10. come aprire i file * .sdf?
- 11. Come aprire i file .SQLite
- 12. Come aprire i file VCE?
- 13. Come aprire i file PDF in Chromium?
- 14. Aprire i file in modalità "rock & roll"
- 15. Aprire i file in memoria significa cosa?
- 16. come aprire il file .mat senza usare MATLAB?
- 17. aprire 100 file in vim
- 18. Richiedi all'utente di salvare/aprire il file in ASP.NET C#
- 19. Matlab: esegue il file senza aprire la GUI, quindi chiude
- 20. Controllare se il file web esiste, senza scaricarlo?
- 21. Impossibile aprire il file di risorse in VS 2015: impossibile aprire il file include afxres.h
- 22. controllare se un file esiste Objective-C
- 23. Come aprire il file vsdx?
- 24. Impossibile aprire il file xls in IE
- 25. file ics - Impossibile aprire il file .ICS allegato in iOS7
- 26. Controllare se il file esistono in Gulp
- 27. MySQL può controllare che il file esista?
- 28. Gestione macro ridefinizione senza modificare i file .h ... C/C++
- 29. ERRORE: impossibile aprire il file sorgente ""
- 30. Impossibile aprire il file include "d3dx9.h"
Ciò richiede l'apertura del file, che l'OP non è auspicabile. –
@remy ma il file è dove la dimensione è memorizzata in modo che le due richieste nella domanda siano contraddittorie –
In realtà no, il file stesso non memorizza la dimensione. Il filesystem lo memorizza. 'GetFileSize()' richiede che il file sia aperto per primo, quindi usa quell'impugnatura per determinare dove si trova il file nel filesystem in modo che possa prendere la dimensione. Se si usa 'FindFirstFile()', interroga il filesystem senza bisogno di aprire il file. –