Как определить размер файла на C?

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

#include <stdio.h>

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

Ответов (13)

Решение

На основе кода 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» .

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

//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);

Вот простая и понятная функция, которая возвращает размер файла.

long get_file_size(char *path)
{
    FILE *fp;
    long size = -1;
    /* Open file for reading */
    fp = fopen(path, "r");
    fseek(fp, 0, SEEK_END);
    size = ftell(fp); 
    fclose(fp);
    return 
}

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

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

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

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

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-битную версию.

У меня есть функция, которая хорошо работает только с stdio.h . Мне он очень нравится, он очень хорошо работает и довольно лаконичен:

size_t fsize(FILE *File) {
    size_t FSZ;
    fseek(File, 0, 2);
    FSZ = ftell(File);
    rewind(File);
    return FSZ;
}

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

Вы можете открыть файл, перейти к 0 смещению относительно нижней части файла с помощью

#define SEEKBOTTOM   2

fseek(handle, 0, SEEKBOTTOM)  

значение, возвращаемое из fseek, - это размер файла.

Я долгое время не программировал на C, но думаю, это должно сработать.

Я нашел метод, использующий fseek и ftell, и ветку с этим вопросом с ответами, что это невозможно сделать на одном только C другим способом.

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

Если вас устраивает библиотека 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;
}

Решение Мэтта должно работать, за исключением того, что это 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;
}

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

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

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

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

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

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

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

Цитата из стандартного документа 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
}