2012-01-24 3 views

ответ

1

Что относительно GetFileSize функция?

+2

Для этого требуется открыть файл, который ОП сказал нежелательно. –

+0

@remy, но файл находится там, где размер хранится, поэтому два запроса в вопросе противоречивы –

+0

На самом деле нет, сам файл не сохраняет размер. Файловая система сохраняет его. 'GetFileSize()' требует, чтобы файл был открыт первым, затем он использует этот дескриптор, чтобы определить, где находится файл в файловой системе, чтобы он мог захватить размер. Если вместо этого вы используете 'FindFirstFile()', он запрашивает файловую систему, не открывая файл. –

41

Вы должны позвонить в 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, будут быстрее. Они могут быть, но вы не узнаете, пока не придумаете это.

+0

Конечно, '' CreateFile() 'может быть довольно медленным, если вы открываете файл на медленном носителе] (http://blogs.msdn.com/b/larryosterman/archive/2004/05/24/140396). aspx), как сетевые диски, но медленность будет связана с задержками доступа к хранилищу, а не из-за того, что файл огромен. –

+0

@ Insilico или ленточные накопители! Но я считаю, что открытие файла - единственный способ найти размер файла, по крайней мере, на окнах. –

+0

@ ДавидХеффернан: Нет! Размер файла находится в заголовке и, следовательно, в каталоге. FindFirstFile(), как показано ниже, будет читать эту информацию без открытия файла. –

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; 

} 
+0

Используйте 'ULARGE_INTEGER' вместо того, чтобы крутить биты' ULONGLONG' вручную, например: 'ULARGE_INTEGER ul; ul.LowPart = FindFileData.nFileSizeLow; ul.HighPart = FindFileData.nFileSizeHigh; ULONGLONG FileSize = ul.QuadPart; '. Кроме того, '% u' ожидает 32-разрядный' unsigned int' в Windows, вам нужно использовать '% Lu' вместо 64-битного целого. –

+2

Я считаю, что FindFirstFile извлекает размер файла, записанный в записи каталога. Обратите внимание, что в некоторых случаях это может быть неточным, например, если файл жестко связан и был изменен с помощью другой жесткой ссылки, или если другое приложение открыто и изменило его. См. Http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx –

+1

Предположительно, проблема, о которой указывает Гарри, заключается в том, что Delphi RTL прекратил использовать FindFirstFile в своей функции sys для размера файла. –

23

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

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

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

The GIST with the code used^можно найти здесь.

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

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

0

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

Смежные вопросы