Bir dosyanın boyutunu bayt olarak nasıl anlayabilirim?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, neden olmasın FILE* file
? -1
Bir dosyanın boyutunu bayt olarak nasıl anlayabilirim?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, neden olmasın FILE* file
? -1
Yanıtlar:
NilObject koduna göre:
#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;
}
değişiklikler:
const char
.struct stat
Değişken adı eksik olan tanım düzeltildi .-1
yerine hata 0
, hangi boş dosya için belirsiz olacaktır. off_t
imzalı bir tür olduğundan bu mümkündür.Hatalı fsize()
bir mesaj yazdırmak istiyorsanız , bunu kullanabilirsiniz:
#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 bit sistemlerde bunu seçenekle derlemelisiniz -D_FILE_OFFSET_BITS=64
, aksi off_t
takdirde yalnızca 2 GB'a kadar olan değerleri tutacaktır. Ayrıntılar için Linux'ta Büyük Dosya Desteğinin "LFS Kullanımı" bölümüne bakın.
fseek
+ kullanın ftell
.
fseek
+ kullanın ftell
. Hayır C Standart özellikle belirtiyor fseek()
için SEEK_END
bir ikili dosya tanımsız davranıştır üzerinde. 7.19.9.2 fseek
fonksiyonu ... anlamlı desteklemeyen bir ikili akış gerek fseek
bir nereden değeri ile çağrıSEEK_END
p dipnot 234 arasındadır ve aşağıdaki belirtildiği. Bağlı C, standartlar, özellikle etiketlerin 267 fseek
için SEEK_END
tanımlanmamış bir davranış gibi bir ikili akışında. .
Kullanma int
. 2 gigabaytın üzerindeki dosyalar bu günlerde kir olarak yaygındır
Kullanma unsigned int
. 4 gigabaytın üzerindeki dosyalar biraz daha az yaygın olan kir olarak yaygındır
IIRC, standart kütüphane off_t
imzasız bir 64 bit tamsayı olarak tanımlar , bu da herkesin kullanması gereken şeydir. 16 exabyte dosyasını asmaya başladığımızda birkaç yıl içinde 128 bit olarak yeniden tanımlayabiliriz.
Windows kullanıyorsanız, şunu kullanmalısınız: GetFileSizeEx - aslında imzalı bir 64 bit tam sayı kullanır, bu nedenle 8 exabyte dosyasıyla ilgili sorunlara başlamaya başlarlar. Aptalca Microsoft! :-)
Matt'in çözümü, C yerine C ++ dışında çalışmalı ve ilk anlatım gerekli olmamalıdır.
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;
}
Sizin için de küme ayracı düzeltildi. ;)
Güncelleme: Bu gerçekten en iyi çözüm değil. Windows'ta 4GB dosyalarla sınırlıdır ve muhtemelen GetFileSizeEx
veya gibi platforma özgü bir arama kullanmaktan daha yavaştır stat64
.
long int
dan ftell()
. (unsigned long)
Döküm, işlevle zaten sınırlı olan aralığı geliştirmez. ftell()
hata durumunda -1 döndürür ve bu, dökümle karıştırılır. İle fsize()
aynı türü döndürmenizi öneririz ftell()
.
** Bunu yapma ( neden? ):
Çevrimiçi bulduğum C99 standart dokümanı alıntılamak: "Dosya konumu göstergesini olduğu gibi dosya sonuna ayarlamak,
fseek(file, 0, SEEK_END)
ikili akış (olası boş karakterlerden dolayı) veya duruma bağlı kodlamaya sahip herhangi bir akış için tanımlanmamış bir davranışa sahiptir ilk vardiya durumunda kesinlikle bitmeyen. **
Hata iletileri bulaşan böylece int ve sonra kullanmak tanımını değiştirin fseek()
ve ftell()
dosya boyutunu belirlemek için.
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
ve ftello
(veya fseek
ve ftell
sen çalışabilirsiniz boyutları dosya üzerinde limitlerine eski ve mutlu olmadan sıkışmış iseniz) bir dosyanın uzunluğunu belirlemek için doğru bir yoldur. stat
tabanlı çözümler işe yaramaz (örneğin blok cihazları gibi) birçok "dosya" konulu ve non-POSIX imsi sistemlere taşınabilir değildir.
POSIX standardı dosya boyutunu almak için kendi yöntemi vardır.
Dahil etsys/stat.h
İşlevi kullanmak başlığı .
stat(3)
.st_size
Mülkü edinin .Not : Boyutu ile sınırlar 4GB
. Fat32
Dosya sistemi değilse 64bit sürümünü kullanın!
#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 doğrudan dosyanın uzunluğunu belirlemek için bir yol sağlar etmez.
Aklımızı kullanmalıyız. Şimdilik arama yaklaşımını kullanacağız!
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);
}
Dosya
stdin
veya kanal ise. POSIX, ANSI C çalışmaz. Dosya bir pipo veya ise
geri dönecektir .0
stdin
Görüş : Bunun yerine POSIX standardını kullanmalısınız. Çünkü 64 bit desteği var.
struct _stat64
ve __stat64()
_Windows için.
Ve bir Windows uygulaması oluşturuyorsanız, GetFileSizeEx API'sini CRT dosyası G / Ç'nin dağınık olması nedeniyle kullanın, özellikle farklı sistemlerde dosya sunumlarındaki özellikler nedeniyle dosya uzunluğunu belirlemek için;)
Std c kütüphanesini kullanmakta sorun yaşıyorsanız:
#include <sys/stat.h>
off_t fsize(char *file) {
struct stat filestat;
if (stat(file, &filestat) == 0) {
return filestat.st_size;
}
return 0;
}
Google'da yapılan hızlı bir arama, fseek ve ftell kullanarak bir yöntem buldu bu soruyla birlikte sadece C ile başka bir şekilde yapılamayan bir konu buldu.
NSPR (Firefox'a güç veren kütüphane) gibi bir taşınabilirlik kütüphanesi kullanabilir veya uygulamasını kontrol edebilirsiniz (oldukça tüylü).
Dosya uzunluğunu bulmak için bu kod kümesini kullandım.
//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);
Bunu dene --
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
Bunun ilk önce yaptığı dosyanın sonuna bakın; daha sonra dosya tanıtıcısının nerede olduğunu bildirin. Son olarak (bu isteğe bağlıdır) dosyanın başına geri sarar. Bunun fp
ikili bir akış olması gerektiğini unutmayın .
file_size dosyanın içerdiği bayt sayısını içerir. (İklime göre. H) imzasız uzun tip 4294967295 bayt (4 gigabayt) ile sınırlı olduğundan, bundan daha büyük dosyalarla ilgilenmeniz gerekiyorsa farklı bir değişken türü bulmanız gerektiğini unutmayın.
ftell
, dosyadan okunabilen bayt sayısını temsil eden bir değer döndürmez.
İşte dosya boyutunu döndüren basit ve temiz bir işlev.
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
}
Dosyayı açabilir, dosyanın alt kısmından göreli olarak 0 ofsetine gidebilirsiniz.
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
fseek'ten döndürülen değer dosyanın boyutudur.
C'de uzun süre kod yazmadım, ama işe yarayacağını düşünüyorum.
Soruya bakarak, ftell
bayt sayısını kolayca alabilirsiniz.
long size = ftell(FILENAME);
printf("total size is %ld bytes",size);
ftell
argüman olarak dosya adı değil dosya tanımlayıcı bekler.
ftell
bir dosya tanımlayıcı beklemez, FILE*
bunun yerine bir dosya bekler . Önce man sayfasına bakın!
fseek()
önce dosyanın sonunu aramak için kullanmanız gerekir ve ayrıca bir dize değil , bir ftell()
bekler FILE *
! Cevabınızı düzeltmek için iyi hizmet edersiniz.