Как я могу определить размер файла в байтах?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
Как я могу определить размер файла в байтах?
#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;
}
Изменения:
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.2 fseek
Функция ... Двоичный поток не обязательно должен поддерживать 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()
.
** Не делайте этого ( почему? ):
Цитата из стандартного документа 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
}
fseeko
и ftello
(или fseek
и ftell
если вы застряли без первого и счастливым с ограничениями на размеры файлов вы можете работать с) , являются правильным способом , чтобы определить длину файла. stat
Решения на основе не работают со многими «файлами» (такими как блочные устройства) и не переносятся на системы, отличные от 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 непосредственно не обеспечивает способ определить длину файла.
Придется использовать свой разум. А пока воспользуемся методом поиска!
#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-битную версию.
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*
вместо этого ожидает . Сначала см. Справочную страницу!