Вам нужно будет использовать библиотечную функцию для получения сведений о файле. Поскольку C полностью независим от платформы, вам нужно будет сообщить нам, для какой платформы / операционной системы вы разрабатываете!
Крис Робертс,
Почему char* file, почему нет FILE* file? -1
-1, потому что файловые функции должны принимать дескрипторы файлов, а не пути к файлам
В 32-битных системах вы должны скомпилировать это с опцией -D_FILE_OFFSET_BITS=64, иначе off_tбудет содержать только значения до 2 ГБ. См. Подробности в разделе «Использование LFS» в статье « Поддержка больших файлов в Linux» .
Это специфично для Linux / Unix - вероятно, стоит указать на это, поскольку в вопросе не указана ОС.
Дрю Холл
1
Вероятно, вы могли бы без проблем изменить возвращаемый тип на ssize_t и преобразовать размер из off_t. Казалось бы, имеет смысл использовать ssize_t :-) (не путать с size_t, которое не имеет знака и не может использоваться для обозначения ошибки.)
Тед Персиваль
1
Для более переносимого кода используйте fseek+, ftellпредложенный Дереком.
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
9
Для более переносимого кода используйте fseek+, ftellпредложенный Дереком. Нет. Стандарт C специально указывает, что fseek()для SEEK_ENDдвоичного файла поведение undefined. 7.19.9.2 fseekФункция ... Двоичный поток не обязательно должен поддерживать fseekвызовы со значением источникаSEEK_END , равным , как указано ниже, из сноски 234 на стр. 267 связанных C стандарта, и которые специфически этикетками , fseekчтобы SEEK_ENDв двоичном потоке в качестве неопределенного поведения. .
Эндрю Хенле
Из руководства gnu libc : ... Системы [не-POSIX] делают различие между файлами, содержащими текст, и файлами, содержащими двоичные данные, и средства ввода и вывода ISO C предусматривают это различие. ... В библиотеке GNU C и во всех системах POSIX нет разницы между текстовыми потоками и двоичными потоками. Когда вы открываете поток, вы получаете тот же поток независимо от того, запрашиваете ли вы двоичный файл. Этот поток может обрабатывать любое содержимое файла и не имеет ограничений, которые иногда имеют текстовые потоки.
Маленький мальчик,
75
Не используйте int. Файлы размером более 2 гигабайт в наши дни стали обычным явлением
Не используйте unsigned int. Файлы размером более 4 гигабайт обычно встречаются как немного менее распространенная грязь.
IIRC стандартная библиотека определяет off_tкак 64-битное целое число без знака, которое следует использовать всем. Мы можем переопределить это значение до 128 бит через несколько лет, когда мы начнем иметь файлы размером 16 эксабайт.
Если вы работаете в Windows, вам следует использовать GetFileSizeEx - он фактически использует 64-битное целое число со знаком, поэтому они начнут сталкиваться с проблемами с 8-ми эксабайтными файлами. Глупый Microsoft! :-)
Я использовал компиляторы, где off_t - 32 бита. Конечно, это во встроенных системах, где файлы размером 4 ГБ встречаются реже. В любом случае, POSIX также определяет off64_t и соответствующие методы, чтобы добавить путаницы.
Аарон Кэмпбелл,
Мне всегда нравятся ответы, которые предполагают наличие Windows и ничего не делают, кроме критики вопроса. Не могли бы вы добавить что-нибудь, совместимое с POSIX?
SS Anne
1
@ JL2210 принятый ответ от Теда Персиваля показывает решение, совместимое с posix, поэтому я не вижу смысла повторять очевидное. Я (и еще 70 человек) подумал, что добавление примечания об окнах и отказ от использования 32-битных целых чисел со знаком для представления размеров файлов было добавлением ценности к этому. Ура
Орион Эдвардс
31
Решение Мэтта должно работать, за исключением того, что это C ++ вместо C, и в первоначальном сообщении нет необходимости.
unsignedlongfsize(char* file){
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsignedlong len = (unsignedlong)ftell(f);
fclose(f);
return len;
}
Поправил и скобу для тебя. ;)
Обновление: это не лучшее решение. В Windows он ограничен файлами размером 4 ГБ и, вероятно, медленнее, чем простой вызов для конкретной платформы, например GetFileSizeExили stat64.
Да, ты должен. Однако, если нет действительно веской причины не писать для конкретной платформы, вам, вероятно, следует просто использовать вызов для конкретной платформы, а не шаблон open / seek-end / tell / close.
Дерек Парк
1
Извините за поздний ответ, но у меня серьезная проблема. Это приводит к зависанию приложения при доступе к файлам с ограниченным доступом (например, защищенным паролем или системным файлам). Есть ли способ при необходимости запросить пароль у пользователя?
Justin
@Justin, вам, вероятно, следует открыть новый вопрос конкретно о проблеме, с которой вы столкнулись, и предоставить подробную информацию о платформе, на которой вы находитесь, о том, как вы получаете доступ к файлам и каково поведение.
Дерек Парк
1
И C99, и C11 возвращаются long intиз ftell(). (unsigned long)приведение не улучшает диапазон, который уже ограничен функцией. ftell()вернуть -1 при ошибке, и это будет запутано с приведением. Предлагаю fsize()вернуть тот же тип, что и ftell().
chux
Согласен. Актерский состав должен был соответствовать оригинальному прототипу в вопросе. Я не могу вспомнить, почему я превратил его в unsigned long вместо unsigned int.
Цитата из стандартного документа C99, который я нашел в Интернете: «Установка индикатора положения файла на конец файла, как и в случае fseek(file, 0, SEEK_END), имеет неопределенное поведение для двоичного потока (из-за возможных завершающих нулевых символов) или для любого потока с кодированием, зависящим от состояния это не обязательно заканчивается в начальном состоянии сдвига. **
Измените определение на int, чтобы можно было передавать сообщения об ошибках, а затем используйте fseek()и ftell()для определения размера файла.
@mezhaka: Этот отчет CERT просто неверен. fseekoи ftello(или fseekи ftellесли вы застряли без первого и счастливым с ограничениями на размеры файлов вы можете работать с) , являются правильным способом , чтобы определить длину файла. statРешения на основе не работают со многими «файлами» (такими как блочные устройства) и не переносятся на системы, отличные от POSIX.
R .. GitHub НЕ ПОМОГАЕТ ICE
1
Это единственный способ получить размер файла во многих системах, несовместимых с posix (например, в моем очень минималистичном mbed)
Earlz
9
POSIX
Стандарт POSIX имеет свой собственный метод получения размера файла.
Включите sys/stat.hзаголовок, чтобы использовать функцию.
Это не стандартный C. Это часть стандарта POSIX, но не стандарта C.
Дерек Парк,
4
А если вы создаете приложение для 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 fstatlong f_d = fileno(i_file);
structstatbuffer;
fstat(f_d, &buffer);
//stores file sizelong file_length = buffer.st_size;
fclose(i_file);
Сначала выполняется поиск до конца файла; затем сообщите, где находится указатель файла. Наконец (это необязательно) он перематывает назад к началу файла. Обратите внимание, что это fpдолжен быть двоичный поток.
file_size содержит количество байтов, содержащихся в файле. Обратите внимание, что, поскольку (согласно climits.h) тип unsigned long ограничен 4294967295 байтами (4 гигабайта), вам нужно будет найти другой тип переменной, если вы, вероятно, будете иметь дело с файлами большего размера.
Это неопределенное поведение для двоичного потока, а для текстового потока ftellне возвращается значение, представляющее количество байтов, которые могут быть прочитаны из файла.
Эндрю Хенле
0
У меня есть функция, которая хорошо работает только с stdio.h. Мне он очень нравится, работает очень хорошо и довольно лаконично:
ftellожидает в качестве аргумента дескриптор файла, а не имя файла.
Barmar
@Barmar, Нет ftellне ожидает файловый дескриптор, FILE*вместо этого ожидает . Сначала см. Справочную страницу!
Подход совершенно неправильный, это постоянно, что ftellбудет возвращаться 0каждый раз!
Этот ответ совершенно неверен, так как, во- fseek()первых , вам нужно использовать сначала для поиска конца файла, а также ftell()ожидает, а FILE *не строку! Вам будет полезно сформулировать свой ответ.
char* file
, почему нетFILE* file
? -1Ответы:
На основе кода 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; }
Изменения:
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» .источник
fseek
+,ftell
предложенный Дереком.fseek
+,ftell
предложенный Дереком. Нет. Стандарт C специально указывает, чтоfseek()
дляSEEK_END
двоичного файла поведение undefined. 7.19.9.2fseek
Функция ... Двоичный поток не обязательно должен поддерживатьfseek
вызовы со значением источникаSEEK_END
, равным , как указано ниже, из сноски 234 на стр. 267 связанных C стандарта, и которые специфически этикетками ,fseek
чтобыSEEK_END
в двоичном потоке в качестве неопределенного поведения. .Не используйте
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
.источник
long int
изftell()
.(unsigned long)
приведение не улучшает диапазон, который уже ограничен функцией.ftell()
вернуть -1 при ошибке, и это будет запутано с приведением. Предлагаюfsize()
вернуть тот же тип, что иftell()
.** Не делайте этого ( почему? ):
Измените определение на 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 }
источник
fseeko
иftello
(илиfseek
иftell
если вы застряли без первого и счастливым с ограничениями на размеры файлов вы можете работать с) , являются правильным способом , чтобы определить длину файла.stat
Решения на основе не работают со многими «файлами» (такими как блочные устройства) и не переносятся на системы, отличные от POSIX.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); }
источник
struct _stat64
и__stat64()
для _Windows.Если вас устраивает библиотека 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);
источник
Попробуй это --
fseek(fp, 0, SEEK_END); unsigned long int file_size = ftell(fp); rewind(fp);
Сначала выполняется поиск до конца файла; затем сообщите, где находится указатель файла. Наконец (это необязательно) он перематывает назад к началу файла. Обратите внимание, что это
fp
должен быть двоичный поток.file_size содержит количество байтов, содержащихся в файле. Обратите внимание, что, поскольку (согласно climits.h) тип unsigned long ограничен 4294967295 байтами (4 гигабайта), вам нужно будет найти другой тип переменной, если вы, вероятно, будете иметь дело с файлами большего размера.
источник
ftell
не возвращается значение, представляющее количество байтов, которые могут быть прочитаны из файла.У меня есть функция, которая хорошо работает только с
stdio.h
. Мне он очень нравится, работает очень хорошо и довольно лаконично:size_t fsize(FILE *File) { size_t FSZ; fseek(File, 0, 2); FSZ = ftell(File); rewind(File); return FSZ; }
источник
Вот простая и понятная функция, которая возвращает размер файла.
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 }
источник
Вы можете открыть файл, перейти к 0 смещению относительно нижнего края файла с помощью
#define SEEKBOTTOM 2 fseek(handle, 0, SEEKBOTTOM)
значение, возвращаемое из fseek, - это размер файла.
Я давно не кодировал на C, но думаю, что это должно сработать.
источник
Глядя на вопрос,
ftell
легко можно получить количество байтов.long size = ftell(FILENAME); printf("total size is %ld bytes",size);
источник
ftell
ожидает в качестве аргумента дескриптор файла, а не имя файла.ftell
не ожидает файловый дескриптор,FILE*
вместо этого ожидает . Сначала см. Справочную страницу!ftell
будет возвращаться0
каждый раз!fseek()
первых , вам нужно использовать сначала для поиска конца файла, а такжеftell()
ожидает, аFILE *
не строку! Вам будет полезно сформулировать свой ответ.