Как узнать размер файла c

от admin

Найти размер файла в байтах в C

В этом посте будет обсуждаться, как найти размер файла в байтах в C.

Стандарт C не предоставляет никакого прямого метода для определения размера файла. Однако мы можем использовать любой из следующих методов, чтобы получить размер файла:

1. Использование stat() функция

В Unix-подобных системах мы можем использовать системные вызовы, совместимые с POSIX. stat() Функция принимает путь к файлу и возвращает структуру, содержащую информацию о файле, на который он указывает. Чтобы получить размер файла в байтах, используйте st_size поле возвращаемой структуры.

Как точно узнать размер файла на диске?

Пишу на C# программу, которая должна высчитывать рекурсивно размер папок и файлов на диске.
Считал, что размер файла на диске равен длине файла, округленной вверх до целого числа кластеров. Также нужно нужно учитывать сжатые/разреженные файлы. Для получения данных о файловой системе использую функцию GetDiskFreeSpaceW, для получения размера файла — функцию GetCompressedFileSizeW.
Но сейчас заметил, что есть маленькие файлы, примерно до 500 байт, которые в меню «Свойства» занимают 0 байт на диске.

  • Вопрос задан 04 апр. 2022
  • 410 просмотров

Простой 6 комментариев

  • Facebook
  • Вконтакте
  • Twitter

Если вы читали статьи по сылкам из ответов, то должны понимать что «правильный» алгоритм тоже приблизительный.
К сожалению статья «The Four Stages of NTFS File Growth.” погребена в недрах убитого MSDN, а там, насколько я помню, было хорошее описание ntfs, поиск в помощь.

Но даже из Just What Is ‘Size on Disk’? понятно что помимо мелких файлов, хранящихся вместе с метаданными прямо в MFT, вы не учитываете еще как минимум, наличие хардлинков и альтернативных потоков
А хардлинки, которых в winSxS овердофига, убьют вам весь алгоритм
Far manager еще очень старается правильно считать размеры папок, загляните в его исходники. Но там c++

ambisinistrone

еще сжатие ntfs существует, и расширенные атрибуты (их не получить простым перечислением файлов в каталоге, по факту это тоже файлы, просто с особым именем)
но еще веселее — дедупликация (на серверных ревизиях), когда одинаковые части разных файлов записаны на диске только один раз

чтобы узнать сколько данных на диске занимают файлы, нужно анализировать mft (кстати именно там хранятся очень мелкие файлы)

How do you determine the size of a file in C?

hippietrail's user avatar

On Unix-like systems, you can use POSIX system calls: stat on a path, or fstat on an already-open file descriptor (POSIX man page, Linux man page).
(Get a file descriptor from open(2) , or fileno(FILE*) on a stdio stream).

Based on NilObject’s code:

  • Made the filename argument a const char .
  • Corrected the struct stat definition, which was missing the variable name.
  • Returns -1 on error instead of 0 , which would be ambiguous for an empty file. off_t is a signed type so this is possible.

If you want fsize() to print a message on error, you can use this:

On 32-bit systems you should compile this with the option -D_FILE_OFFSET_BITS=64 , otherwise off_t will only hold values up to 2 GB. See the "Using LFS" section of Large File Support in Linux for details.

Peter Cordes's user avatar

Don’t use int . Files over 2 gigabytes in size are common as dirt these days

Don’t use unsigned int . Files over 4 gigabytes in size are common as some slightly-less-common dirt

IIRC the standard library defines off_t as an unsigned 64 bit integer, which is what everyone should be using. We can redefine that to be 128 bits in a few years when we start having 16 exabyte files hanging around.

If you’re on windows, you should use GetFileSizeEx — it actually uses a signed 64 bit integer, so they’ll start hitting problems with 8 exabyte files. Foolish Microsoft! 🙂

Matt’s solution should work, except that it’s C++ instead of C, and the initial tell shouldn’t be necessary.

Fixed your brace for you, too. 😉

Update: This isn’t really the best solution. It’s limited to 4GB files on Windows and it’s likely slower than just using a platform-specific call like GetFileSizeEx or stat64 .

Quoting the C99 standard doc that i found online: «Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END) , has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state.**

Change the definition to int so that error messages can be transmitted, and then use fseek() and ftell() to determine the file size.

POSIX

The POSIX standard has its own method to get file size.
Include the sys/stat.h header to use the function.

Synopsis

  • Get file statistics using stat(3) .
  • Obtain the st_size property.

Examples

Note: It limits the size to 4GB . If not Fat32 filesystem then use the 64bit version!

ANSI C (standard)

The ANSI C doesn’t directly provides the way to determine the length of the file.
We’ll have to use our mind. For now, we’ll use the seek approach!

Synopsis

  • Seek the file to the end using fseek(3) .
  • Get the current position using ftell(3) .

Example

If the file is stdin or a pipe. POSIX, ANSI C won’t work.
It will going return 0 if the file is a pipe or stdin .

Opinion: You should use POSIX standard instead. Because, it has 64bit support.

And if you’re building a Windows app, use the GetFileSizeEx API as CRT file I/O is messy, especially for determining file length, due to peculiarities in file representations on different systems 😉

Читать:
Как разделить строку на слова c

If you’re fine with using the std c library:

I used this set of code to find the file length.

I found a method using fseek and ftell and a thread with this question with answers that it can’t be done in just C in another way.

You could use a portability library like NSPR (the library that powers Firefox).

In plain ISO C, there is only one way to determine the size of a file which is guaranteed to work: To read the entire file from the start, until you encounter end-of-file.

However, this is highly inefficient. If you want a more efficient solution, then you will have to either

  • rely on platform-specific behavior, or
  • revert to platform-specific functions, such as stat on Linux or GetFileSize on Microsoft Windows.

In contrast to what other answers have suggested, the following code is not guaranteed to work:

Even if we assume that the data type long is large enough to represent the file size (which is questionable on some platforms, most notably Microsoft Windows), the posted code has the following problems:

The posted code is not guaranteed to work on text streams, because according to §7.21.9.4 ¶2 of the ISO C11 standard, the value of the file position indicator returned by ftell contains unspecified information. Only for binary streams is this value guaranteed to be the number of characters from the beginning of the file. There is no such guarantee for text streams.

The posted code is also not guaranteed to work on binary streams, because according to §7.21.9.2 ¶3 of the ISO C11 standard, binary streams are not required to meaningfully support SEEK_END .

That being said, on most common platforms, the posted code will work, if we assume that the data type long is large enough to represent the size of the file.

However, on Microsoft Windows, the characters \r\n (carriage return followed by line feed) will be translated to \n for text streams (but not for binary streams), so that the file size you get will count \r\n as two bytes, although you are only reading a single character ( \n ) in text mode. Therefore, the results you get will not be consistent.

Программирование C — Как получить размер файла?

Как оказалось, узнать размер файла в языке C — совсем нетривиальная задача. В процессе её решения как минимум вы обязательно столкнетесь с переполнением целочисленного типа данных. В данной статье я приведу 4 способа получения размера файла с использованием функций из стандартной библиотеки C, функций из библиотеки POSIX и функций из библиотек Windows.
Способ 1: решение «в лоб» (скомпилируется везде, но работает очень долго)
Мы просто откроем файл в бинарном режиме и в цикле считаем из него байт за байтом.

Очевидным недостатком способа является скорость работы. Если у нас файл будет на много гигабайт, то только размер файла будет считаться относительно долго (это сколько байт то надо считать?), а надо же еще остальную программу выполнять.
Достоинство такого способа — работать должен на любой платформе. Ну и конечно можно ускорить процесс за счет считывания бОльшего количества байт.

Способ 2: с использованием функций fseek и ftell (ограничен для объемных файлов и работает не всегда верно)

Данный способ основан на использовании функций стандартной библиотеки C: fseek и ftell. Что происходит — открываем файл в бинарном режиме, перемещаем внутренний указатель положения в файле сразу в конец с помощью fseek, получаем номер последнего байта с помощью ftell.

Проблем у данного способа несколько.
Первое — это возвращаемый тип функции ftell. У разных компиляторов на разных платформах по разному. Если у вас 32х битная система, то данный способ будет работать только для файлов, размером меньше 2048 Мб, поскольку максимальное значение для возвращаемого функцией типа long там будет 2147483647. На системах с большей разрядностью будет работать лучше, из-за большего значения максимума для long. Но подобная нестабильность будет мешать. Хотя у меня на 64х битой системе на компиляторе gcc данный способ для файлов больше 8 Гб выводил некорректные значения.
Второе — гарантированность работы fseek и ftell. Коротко говоря, на разных платформах работает по-разному. Где то будет точно возвращать значение положения последнего байта, где то будет возвращать неверное значение. То есть точность данного способа негарантированна.

Плюсом является то, что эти функции из стандартной библиотеки — скомпилируется почти везде.

Стоит сказать, что хитрые инженеры из Microsoft придумали функции _fseeki64 и _ftelli64, которые, как понятно из их названия, работают с int64, что решает проблему с размером файла в MSVC под Windows.

Способ 3: (под Linux (POSIX))

Данный способ основан на использовании системном вызове fstat с использованием специальной структуры struct stat. Как работает: открываем файл через open() или fopen(), вызываем fstat для дескриптора файла (если открыли через fopen, то в fstat надо положить результат fileno от указателя потока FILE), указав на буферную структуру для результатов, и получаем значения поля буферной структуры st_size.

Похожие статьи