Как вы определяете размер файла в C?


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

#include <stdio.h>

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

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; 
}

изменения:

  • сделал аргумент filename 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 для сведения.

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

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

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

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

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

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.

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

цитируя стандартный документ 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
}

Если вы в порядке с использованием библиотеки 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;
}

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

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

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

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

//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;
    /* Open file for reading */
    fp = fopen(path, "r");
    fseek(fp, 0, SEEK_END);
    return ftell(fp); 
}

попробовать это...

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

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

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

вам нужно будет использовать функцию библиотеки для получения сведений о файле. Поскольку C полностью независим от платформы, вам нужно будет сообщить нам, для какой платформы / операционной системы вы разрабатываете!

глядя на вопрос, ftell можно легко получить количество байт.

  long size ;
  size = ftell(FILENAME);
  printf("total size is %ld bytes",size);

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

#define SEEKBOTTOM   2

fseek(handle, 0, SEEKBOTTOM)  

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

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