Как вы определяете размер файла в C? - PullRequest
129 голосов
/ 12 августа 2008

Как определить размер файла в байтах?

#include <stdio.h>

unsigned int fsize(char* file){
  //what goes here?
}

Ответы [ 14 ]

131 голосов
/ 12 августа 2008

На основе кода NilObject:

#include <sys/stat.h>
#include <sys/types.h>

off_t fsize(const char *filename) {
    struct stat st; 

    if (stat(filename, &st) == 0)
        return st.st_size;

    return -1; 
}

Изменения:

  • Сделал аргумент имени файла a const char.
  • Исправлено определение struct stat, в котором отсутствовало имя переменной.
  • Возвращает -1 при ошибке вместо 0, что было бы неоднозначно для пустого файла. off_t является типом со знаком, так что это возможно.

Если вы хотите fsize() напечатать сообщение об ошибке, вы можете использовать это:

#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

off_t fsize(const char *filename) {
    struct stat st;

    if (stat(filename, &st) == 0)
        return st.st_size;

    fprintf(stderr, "Cannot determine size of %s: %s\n",
            filename, strerror(errno));

    return -1;
}

В 32-разрядных системах вы должны скомпилировать это с опцией -D_FILE_OFFSET_BITS=64, в противном случае off_t будет содержать значения только до 2 ГБ. Подробнее см. Раздел «Использование LFS» Поддержка больших файлов в Linux .

70 голосов
/ 12 августа 2008

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

Не используйте unsigned int. Файлы размером более 4 гигабайт обычны как немного менее распространенная грязь

Стандартная библиотека IIRC определяет off_t как 64-разрядное целое число без знака, которым должны пользоваться все. Мы можем переопределить его как 128-битный через несколько лет, когда у нас появятся 16 эксабайтных файлов.

Если вы работаете в Windows, вы должны использовать GetFileSizeEx - он на самом деле использует 64-разрядное целое число со знаком, поэтому они начнут сталкиваться с проблемами с 8 эксабайтными файлами. Глупый Microsoft! : -)

29 голосов
/ 12 августа 2008

Решение Мэтта должно работать, за исключением того, что это C ++ вместо C, и первоначальное сообщение не должно быть необходимым.

unsigned long fsize(char* file)
{
    FILE * f = fopen(file, "r");
    fseek(f, 0, SEEK_END);
    unsigned long len = (unsigned long)ftell(f);
    fclose(f);
    return len;
}

Исправил вашу скобку для вас тоже. ;)

Обновление: на самом деле это не лучшее решение. Он ограничен 4 ГБ файлами в Windows и, вероятно, медленнее, чем просто вызов конкретной платформы, такой как GetFileSizeEx или stat64.

12 голосов
/ 12 августа 2008

** Не делайте этого ( почему? ):

Цитируя стандартный документ C99, который я нашел в Интернете: «Установка индикатора положения файла в конец файла, как и в случае fseek (file, 0, SEEK_END), имеет неопределенное поведение для двоичного потока (из-за возможного завершающего нуля символов) или для любого потока с кодированием, зависящим от состояния, которое не обязательно заканчивается в начальном состоянии сдвига. **

Измените определение на int, чтобы можно было передавать сообщения об ошибках, а затем используйте fseek () и ftell () для определения размера файла.

int fsize(char* file) {
  int size;
  FILE* fh;

  fh = fopen(file, "rb"); //binary mode
  if(fh != NULL){
    if( fseek(fh, 0, SEEK_END) ){
      fclose(fh);
      return -1;
    }

    size = ftell(fh);
    fclose(fh);
    return size;
  }

  return -1; //error
}
5 голосов
/ 09 января 2019

1001 * POSIX * Стандарт POSIX имеет собственный метод получения размера файла.
Включите заголовок sys/stat.h для использования функции. Синопсис Получить статистику файла, используя stat(3). Получить свойство st_size. Примеры Примечание : ограничивает размер 4GB. Если не Fat32 файловая система, тогда используйте 64-битную версию! #include <stdio.h> #include <sys/stat.h> int main(int argc, char** argv) { struct stat info; stat(argv[1], &info); // 'st' is an acronym of 'stat' printf("%s: size=%ld\n", argv[1], info.st_size); } #include <stdio.h> #include <sys/stat.h> int main(int argc, char** argv) { struct stat64 info; stat64(argv[1], &info); // 'st' is an acronym of 'stat' printf("%s: size=%ld\n", argv[1], info.st_size); } ANSI C (стандарт)

ANSI C не позволяет напрямую определить длину файла.
Нам придется использовать наш разум. Сейчас мы будем использовать подход поиска!

Синопсис

  • Искать файл до конца, используя fseek(3).
  • Получить текущую позицию, используя ftell(3).
* * Пример тысяча сорок-девять
#include <stdio.h>

int main(int argc, char** argv)
{
    FILE* fp = fopen(argv[1]);
    int f_size;

    fseek(fp, 0, SEEK_END);
    f_size = ftell(fp);
    rewind(fp); // to back to start again

    printf("%s: size=%ld", (unsigned long)f_size);
}

Если файл stdin или труба. POSIX, ANSI C не будет работать.
Будет возвращаться 0, если файл представляет собой канал или stdin.

Мнение : Вместо этого вы должны использовать стандарт POSIX . Потому что он поддерживает 64 бита.

5 голосов
/ 12 августа 2008

Если вы хорошо используете библиотеку std c:

#include <sys/stat.h>
off_t fsize(char *file) {
    struct stat filestat;
    if (stat(file, &filestat) == 0) {
        return filestat.st_size;
    }
    return 0;
}
4 голосов
/ 12 августа 2008

А если вы создаете приложение для Windows, используйте API GetFileSizeEx , так как ввод / вывод файла CRT запутан, особенно для определения длины файла, из-за особенностей представления файлов в разных системах;)

3 голосов
/ 12 августа 2008

Быстрый поиск в Google нашел метод, использующий fseek и ftell и цепочку с этим вопросом, ответы на которые не могут быть выполнены просто на языке Си по-другому.

Вы можете использовать библиотеку переносимости, такую ​​как NSPR (библиотека, поддерживающая Firefox) или проверить ее реализацию (скорее волосатую).

1 голос
/ 30 декабря 2016

Попробуйте это -

fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);

Что это делает в первую очередь, искать в конце файла; затем сообщите, где находится указатель файла. И наконец (это необязательно), он перематывает назад к началу файла. Обратите внимание, что fp должен быть двоичным потоком.

file_size содержит количество байтов в файле. Обратите внимание, что поскольку (в соответствии с climits.h) тип unsigned long ограничен 4294967295 байтами (4 гигабайта), вам потребуется найти другой тип переменной, если вы, вероятно, имеете дело с файлами большего размера.

1 голос
/ 08 февраля 2014

Я использовал этот набор кода, чтобы найти длину файла.

//opens a file with a file descriptor
FILE * i_file;
i_file = fopen(source, "r");

//gets a long from the file descriptor for fstat
long f_d = fileno(i_file);
struct stat buffer;
fstat(f_d, &buffer);

//stores file size
long file_length = buffer.st_size;
fclose(i_file);
...