Як я можу визначити розмір файлу в байтах?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, чому ні FILE* file
? -1
Як я можу визначити розмір файлу в байтах?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
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
бінарного файлу не визначено поведінку. 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;
}
Фіксований брекет теж для вас. ;)
Оновлення: Це насправді не найкраще рішення. Він обмежений 4 Гб файлами в Windows, і, ймовірно, повільніше, ніж просто використання виклику, який залежить від платформи, як 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.
А якщо ви створюєте додаток для Windows, використовуйте API GetFileSizeEx, оскільки введення / виведення файлів CRT є безладним, особливо для визначення довжини файлів, через особливості представлення файлів у різних системах;)
Якщо ви добре використовуєте бібліотеку 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;
}
Швидкий пошук в 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) довгий неподписаний тип обмежений 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*
замість цього. Перегляньте першу сторінку чоловіка!
fseek()
щоб шукати кінець файлу, а також, ftell()
очікує FILE *
, що не, а рядок! Вам би добре послужили, щоб уточнити свою відповідь.