Як я можу визначити розмір файлу в байтах?
#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 *, що не, а рядок! Вам би добре послужили, щоб уточнити свою відповідь.