Как вы определяете размер файла на C?
Вопрос
Как я могу определить размер файла в байтах?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
Решение
Основано на коде 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 равным
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 экзабайт.Глупый Microsoft!:-)
Решение Мэтта должно работать, за исключением того, что это 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
.
** Не делай этого (почему?):
Цитирую стандартный документ 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;
}
POSIX
Тот Самый POSIX у standard есть свой собственный метод получения размера файла.
Включать в себя 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 напрямую не предоставляет способ определения длины файла.
Нам придется напрячь свой разум.На данный момент мы будем использовать подход seek!
Краткий обзор
Пример
#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-битную поддержку.
И если вы создаете приложение для 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);
Попробуй это --
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
Что это делает, так это, во-первых, обращается к концу файла;затем сообщите, где находится указатель на файл.Наконец (это необязательно), он перематывает назад к началу файла.Обратите внимание , что fp
это должен быть двоичный поток.
file_size содержит количество байт, содержащихся в файле.Обратите внимание, что поскольку (согласно climits.h ) тип unsigned long ограничен 4294967295 байтами (4 гигабайта), вам нужно будет найти другой тип переменной, если вы, вероятно, будете иметь дело с файлами большего размера.
Вот простая и понятная функция, которая возвращает размер файла.
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);
fp.close();
return
}
Вам нужно будет использовать библиотечную функцию для извлечения сведений о файле.Поскольку C полностью не зависит от платформы, вам нужно будет сообщить нам, для какой платформы / операционной системы вы разрабатываете!
Рассматривая этот вопрос, ftell
можно легко получить количество байт.
long size ;
size = ftell(FILENAME);
printf("total size is %ld bytes",size);
Вы можете открыть файл, перейдя к смещению 0 относительно нижней части файла с помощью
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
значение, возвращаемое из fseek, является размером файла.
Я долгое время не программировал на C, но я думаю, что это должно сработать.