Cum determinați dimensiunea unui fișier în C?

Cum pot determina dimensiunea unui fișier, în octeți?

#include 

unsigned int fsize(char* file){
  //what goes here?
}
0
fr hi bn

12 răspunsuri

Nu utilizați int . Fișiere de peste 2 gigabytes în dimensiune sunt comune ca murdărie în aceste zile

Nu utilizați unsigned int . Fișiere cu dimensiunea de peste 4 gigaocteți sunt comune, întrucât unele murdăriri puțin mai frecvente

IIRC biblioteca standard definește off_t ca un număr întreg nesemnat de 64 de biți, ceea ce ar trebui să fie folosit de toată lumea. Putem redefini ca aceasta sa fie de 128 de biti in cativa ani cand vom incepe sa avem 16 fisiere exabyte in jurul nostru.

If you're on windows, you should use GetFileSizeEx - it actually uses a signed 64 bit integer, so they'll start hitting problems with 8 exabyte files. Foolish Microsoft! :-)

0
adăugat
Am folosit compilatoare unde off_t este de 32 de biți. Acordat, aceasta este pe sistemele încorporate în care fișierele de 4 GB sunt mai puțin frecvente. Oricum, POSIX definește de asemenea off64_t și metodele corespunzătoare pentru a adăuga la confuzie.
adăugat autor Aaron Campbell, sursa

** Nu faceți acest lucru ( de ce? ):

Citând documentul standard C99 pe care l-am găsit online: "Setarea indicatorului poziției fișierului la sfârșitul fișierului, ca și în cazul fseek (fișier, 0, SEEK_END), are un comportament nedefinit pentru un flux binar caractere) sau pentru orice flux cu codare dependentă de stat care nu se încheie cu siguranță în starea de schimbare inițială. **

Modificați definiția la int astfel încât mesajele de eroare să poată fi transmise și apoi utilizați fseek() și ftell() pentru a determina dimensiunea fișierului.

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
}
0
adăugat
Aceasta este singura modalitate de a obține dimensiunea fișierului pe multe sisteme care nu respectă pozițiile posibile (cum ar fi mormântul meu foarte minimalist)
adăugat autor Earlz, sursa
@mezhaka: Raportul CERT este pur și simplu greșit. fseeko și ftello (sau fseek și ftell dimensiunile fișierelor cu care puteți lucra) reprezintă metoda corectă de determinare a lungimii unui fișier. nu funcționează în multe "fișiere" (cum ar fi dispozitivele blocate) și nu sunt portabile sistemelor non-POSIX.
adăugat autor R.., sursa

Va trebui să utilizați o funcție de bibliotecă pentru a prelua detaliile unui fișier. Deoarece C este complet independent de platformă, va trebui să ne comunicați ce platformă/sistem de operare vă dezvoltați!

0
adăugat

Puteți deschide fișierul, mergeți la 0 relative offset din partea de jos a fișierului cu

#define SEEKBOTTOM   2

fseek(handle, 0, SEEKBOTTOM)  

valoarea returnată de la fseek este dimensiunea fișierului.

Nu am codat mult timp în C, dar cred că ar trebui să funcționeze.

0
adăugat
Nu trebuie să definiți ceva de genul SEEKBOTTOM. #include fseek (mâner, 0, SEEK_END);
adăugat autor sigjuice, sursa

Soluția lui Matt ar trebui să funcționeze, cu excepția faptului că este C ++ în loc de C, iar comunicarea inițială nu ar trebui să fie necesară.

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;
}

Ți-ai fixat și brățara pentru tine. ;)

Actualizare: Aceasta nu este cu adevărat cea mai bună soluție. Se limitează la fișiere de 4 GB pe Windows și este probabil mai lent decât să folosească un apel specific pentru platformă, cum ar fi GetFileSizeEx sau stat64 .

0
adăugat
Da ar trebui. Cu toate acestea, cu excepția cazului în care există un motiv foarte convingător, nu scrieți specificul platformei, totuși, ar trebui să utilizați probabil un apel specific platformei, mai degrabă decât modelul open/seek-end/tell/close.
adăugat autor Derek Park, sursa
@ Probabil, probabil ar trebui să deschideți o nouă întrebare specifică problemei în care vă aflați și să oferiți detalii despre platforma pe care o utilizați, cum accesați fișierele și ce este comportamentul.
adăugat autor Derek Park, sursa
Sunt de acord. Distribuția trebuia să se potrivească cu prototipul original al întrebării. Nu-mi amintesc de ce am transformat-o în nesemnate lungi în loc de int unsigned, deși.
adăugat autor Derek Park, sursa
Îmi pare rău pentru răspunsul târziu, dar am o problemă majoră aici. Cauzează suspendarea aplicației atunci când accesează fișierele restricționate (cum ar fi fișierele protejate prin parolă sau sistemul). Există o modalitate de a solicita utilizatorului o parolă atunci când este necesar?
adăugat autor Justin, sursa
Atât C99 cât și C11 returnează long int din ftell() . (castron nesemnat lung) nu îmbunătățește intervalul astfel cum a fost deja limitat de funcție. ftell() returnați -1 pe eroare și care sunt obfuscate cu distribuția. Sugerați fsize() returnează același tip ca și ftell() .
adăugat autor chux, sursa

Dacă sunteți bine în utilizarea bibliotecii std c:

#include 
off_t fsize(char *file) {
    struct stat filestat;
    if (stat(file, &filestat) == 0) {
        return filestat.st_size;
    }
    return 0;
}
0
adăugat
Nu este standard C. Este parte din standardul POSIX, dar nu și standardul C.
adăugat autor Derek Park, sursa

Incearca asta --

fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);

Ceea ce face mai întâi este să căutați la sfârșitul dosarului; apoi, raportați unde este pointerul fișierului. În cele din urmă (acest lucru este opțional) se întoarce la începutul fișierului. Rețineți că fp ar trebui să fie un flux binar.

file_size conține numărul de octeți care conține fișierul. Rețineți că, deoarece (în conformitate cu climits.h), tipul nesemnificativ lung este limitat la 4294967295 octeți (4 gigaocteți), va trebui să găsiți un alt tip de variabilă dacă aveți de-a face cu fișiere mai mari decât acestea.

0
adăugat
Acesta este un comportament nedefinit pentru un flux binar, iar pentru un flux de text ftell nu se întoarce o valoare reprezentativă pentru numărul de octeți care pot fi citiți din fișier.
adăugat autor Andrew Henle, sursa
Cum diferă aceasta de răspunsul lui Derek de acum 8 ani?
adăugat autor P.P., sursa

O căutare rapidă în Google a găsit o metodă folosind fseek și ftell și un fir cu această întrebare cu răspunsuri că nu se poate face doar în C într-un alt mod.

You could use a portability library like NSPR (the library that powers Firefox) or check its implementation (rather hairy).

0
adăugat

Bazat pe codul lui NilObject:

#include 

off_t fsize(const char *filename) {
    struct stat st; 

    if (stat(filename, &st) == 0)
        return st.st_size;

    return -1; 
}

Schimbări:

  • S-a făcut argumentul const char
  • S-a corectat definiția struct stat , din care lipsea numele variabilei.
  • Returneaza -1 pentru eroare in loc de 0 , ceea ce ar fi ambiguu pentru un fisier gol. off_t este un tip semnat, astfel încât acest lucru este posibil.

Dacă doriți fsize() pentru a imprima un mesaj pe eroare, puteți folosi acest lucru:

#include 
#include 
#include 
#include 

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;
}

La sistemele pe 32 de biți trebuie să compilați această opțiune cu -D_FILE_OFFSET_BITS = 64 , altfel off_t va menține valori de până la 2 GB. Vedeți secțiunea "Utilizarea LFS" din Suport pentru fișiere mari în Linux pentru detalii.

0
adăugat
Pentru un cod mai portabil, folosiți fseek + ftell așa cum a propus Derek. -std.org/jtc1/sc22/wg14/www/docs/n1256.pdf "rel =" nofollow noreferrer "> C Standard specifică faptul că fseek() la SEEK_END pe un fișier binar este un comportament nedefinit. 7.19.9.2 Funcția fseek ... Un flux binar nu are nevoie să suporte în mod semnificativ apelurile fseek SEEK_END , și după cum se menționează mai jos, care este din nota de subsol 234 de la p. 267 din standardul C legat ș
adăugat autor Andrew Henle, sursa
Acest lucru este specific Linux/Unix - probabil merită să subliniez faptul că, deoarece întrebarea nu a specificat un sistem de operare.
adăugat autor Drew Hall, sursa
Pentru un cod mai portabil, folosiți fseek + ftell așa cum a propus Derek.
adăugat autor Ciro Santilli 包子露宪 六四事件 法轮功, sursa
S-ar putea să schimbați tipul returului la ssize_t și să mutați dimensiunea dintr-un off_t fără probleme. S-ar părea că are mai mult sens să folosești un ssize_t :-) (Să nu fii confundat cu size_t care nu este semnat și nu poate fi folosit pentru a indica eroarea.)
adăugat autor Ted Percival, sursa

Am folosit acest set de cod pentru a găsi lungimea fișierului.

//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);
0
adăugat

Privind la întrebare, ftell poate obține cu ușurință numărul de octeți.

  long size ;
  size = ftell(FILENAME);
  printf("total size is %ld bytes",size);
0
adăugat
ftell așteaptă ca descriptor un descriptor de fișier, nu un nume de fișier.
adăugat autor Barmar, sursa

Iată o funcție simplă și curată care returnează dimensiunea fișierului.

long get_file_size(char *path)
{
    FILE *fp;
    /* Open file for reading */
    fp = fopen(path, "r");
    fseek(fp, 0, SEEK_END);
    return ftell(fp); 
}
0
adăugat
Nu trebuie să închideți fișierul?
adăugat autor Jerry Jeremiah, sursa