आप C में किसी फ़ाइल का आकार कैसे निर्धारित करते हैं?


137

मैं बाइट्स में फ़ाइल के आकार का पता कैसे लगा सकता हूं?

#include <stdio.h>

unsigned int fsize(char* file){
  //what goes here?
}

किसी फ़ाइल के विवरण को पुनः प्राप्त करने के लिए आपको लाइब्रेरी फ़ंक्शन का उपयोग करने की आवश्यकता है। जैसा कि सी पूरी तरह से प्लेटफ़ॉर्म स्वतंत्र है, आपको यह बताने की ज़रूरत है कि आप किस प्लेटफ़ॉर्म / ऑपरेटिंग सिस्टम को विकसित कर रहे हैं!
क्रिस रॉबर्ट्स

क्यों char* file, क्यों नहीं FILE* file? -1
श्री ऑस्कर

-1 क्योंकि फ़ाइल फ़ंक्शंस को फ़ाइल डिस्क्रिप्टर स्वीकार करना चाहिए जो पथ नहीं दर्ज करते हैं
श्री ऑस्कर

जवाबों:


144

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 जीबी तक के मूल्य होंगे। विवरण के लिए लिनक्स में बड़े फ़ाइल समर्थन के "एलएफएस का उपयोग करना" अनुभाग देखें।


19
यह लिनक्स / यूनिक्स विशिष्ट है - शायद यह इंगित करने के लायक है कि सवाल ओएस निर्दिष्ट नहीं करता है।
ड्रू हॉल

1
आप शायद ssize_t में वापसी प्रकार बदल सकते हैं और किसी भी परेशानी के बिना off_t से आकार डाल सकते हैं। यह एक ssize_t :-) का उपयोग करने के लिए और अधिक समझ बनाने के लिए प्रतीत होता है (साइज़_टी के साथ भ्रमित नहीं होना चाहिए जो अहस्ताक्षरित है और त्रुटि को इंगित करने के लिए उपयोग नहीं किया जा सकता है।)
टेड पर्किवल

1
अधिक पोर्टेबल कोड के लिए, डेरेक द्वारा प्रस्तावित fseek+ के ftellरूप में उपयोग करें ।
सिरो सेंटिल्ली 郝海东 i i i 法轮功 '

9
अधिक पोर्टेबल कोड के लिए, डेरेक द्वारा प्रस्तावित fseek+ के ftellरूप में उपयोग करें । सं सी स्टैंडर्ड विशेष रूप से कहा गया है कि fseek()करने के लिए SEEK_ENDपर एक बाइनरी फ़ाइल अपरिभाषित व्यवहार है। 7.19.9.2 fseekफ़ंक्शन ... बाइनरी स्ट्रीम को सार्थक रूप से fseekकॉल का समर्थन करने की आवश्यकता नहीं हैSEEK_END , और जैसा कि नीचे उल्लेख किया गया है, जो पी पर फुटनोट 234 से है। लिंक किए गए सी स्टैंडर्ड, और जो विशेष रूप से लेबल की 267 fseekको SEEK_ENDअपरिभाषित व्यवहार के रूप में एक बाइनरी धारा में। ।
एंड्रयू हेनले

74

उपयोग न करें int। 2 गीगाबाइट से अधिक आकार की फाइलें इन दिनों गंदगी के रूप में आम हैं

उपयोग न करें unsigned int। आकार में 4 गीगाबाइट से अधिक की फाइलें कुछ कम-सामान्य गंदगी के रूप में आम हैं

IIRC मानक पुस्तकालय off_tएक अहस्ताक्षरित 64 बिट पूर्णांक के रूप में परिभाषित करता है , जो कि सभी को उपयोग करना चाहिए। जब हम 16 एक्सबायटे फाइलें चारों ओर लटकाना शुरू करते हैं, तो हम कुछ वर्षों में 128 बिट्स को फिर से परिभाषित कर सकते हैं।

यदि आप खिड़कियों पर हैं, तो आपको GetFileSizeEx का उपयोग करना चाहिए - यह वास्तव में एक हस्ताक्षरित 64 बिट पूर्णांक का उपयोग करता है, इसलिए वे 8 एक्साबाइट फ़ाइलों के साथ समस्याओं को मारना शुरू कर देंगे। मूर्ख Microsoft! :-)


1
मैंने ऐसे कंपाइलर का उपयोग किया है जहाँ off_t 32 बिट्स है। दी, यह एम्बेडेड सिस्टम पर है जहाँ 4GB फाइलें कम आम हैं। वैसे भी, POSIX भी ऑफ64_t और इसी तरीकों को भ्रम में जोड़ने के लिए परिभाषित करता है।
एरोन कैम्पबेल

मुझे हमेशा ऐसे उत्तर पसंद आते हैं जो विंडोज मान लेते हैं और कुछ नहीं करते हैं लेकिन सवाल की आलोचना करते हैं। क्या आप कृपया कुछ ऐसा जोड़ सकते हैं जो POSIX- अनुरूप हो?
एसएस ऐनी

1
@ JL2210 ने टेड पर्किवल से स्वीकार किए गए उत्तर को एक पॉज़िक्स अनुरूप समाधान दिखाया है, इसलिए मुझे स्पष्ट दोहराने में कोई समझदारी नहीं है। मैंने (70 और लोगों ने) सोचा था कि खिड़कियों के बारे में नोट जोड़ना और फ़ाइल आकार का प्रतिनिधित्व करने के लिए हस्ताक्षरित 32 बिट पूर्णांक का उपयोग नहीं करना, उसके शीर्ष पर एक मूल्य-जोड़ था। चीयर्स
ओरियन एडवर्ड्स

30

मैट के समाधान को काम करना चाहिए, सिवाय इसके कि यह 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;
}

आप के लिए अपने कंस तय की, भी। ;)

अद्यतन: यह वास्तव में सबसे अच्छा समाधान नहीं है। यह विंडोज पर 4GB फाइलों तक ही सीमित है और यह सिर्फ तरह एक प्लेटफ़ॉर्म-विशिष्ट कॉल का उपयोग करने से होने की संभावना धीमी है GetFileSizeExया stat64


हाँ तुम्हें करना चाहिए। हालाँकि, जब तक कि वास्तव में सम्मोहक कारण प्लेटफ़ॉर्म-विशिष्ट नहीं लिखा जाता है, हालाँकि, आपको शायद खुले / तलाश-अंत / बताने / बंद करने के बजाय एक प्लेटफ़ॉर्म-विशिष्ट कॉल का उपयोग करना चाहिए।
डेरेक पार्क

1
देर से जवाब के बारे में क्षमा करें, लेकिन मैं यहाँ एक प्रमुख मुद्दा रहा हूँ। यह प्रतिबंधित फ़ाइलों (जैसे पासवर्ड संरक्षित या सिस्टम फ़ाइलों) तक पहुंचते समय एप्लिकेशन को लटका देता है। क्या जरूरत पड़ने पर उपयोगकर्ता से पासवर्ड मांगने का कोई तरीका है?
जस्टिन

@ जस्टिन, आपको संभवतः एक नया प्रश्न खोलना चाहिए, विशेष रूप से उस मुद्दे के बारे में जो आप चला रहे हैं, और उस मंच के बारे में जानकारी दें, जिस पर आप फ़ाइलों तक पहुँच रहे हैं, और व्यवहार क्या है।
डेरेक पार्क

1
C99 और C11 दोनों long intसे लौटते हैं ftell()(unsigned long)कास्टिंग पहले से सीमित फ़ंक्शन के अनुसार सीमा में सुधार नहीं करता है। ftell()त्रुटि पर वापसी -1 और कि कलाकारों के साथ obfuscated मिलता है। सुझाव के fsize()रूप में उसी प्रकार लौटें ftell()
chux -

मैं सहमत हूँ। प्रश्न में मूल प्रोटोटाइप का मिलान करना था। मैं याद नहीं कर सकता कि मैंने इसे अहस्ताक्षरित इंट के बजाय लंबे समय तक क्यों बदल दिया।
डेरेक पार्क

15

** ऐसा मत करो ( क्यों? ):

C99 मानक डॉक का उद्धरण, जो मुझे ऑनलाइन मिला था: "फ़ाइल स्थिति सूचक को एंड-टू-फ़ाइल के रूप में सेट करना, जैसे fseek(file, 0, SEEK_END)कि द्विआधारी धारा के लिए अपरिभाषित व्यवहार (संभावित अनुगामी अशक्त वर्णों के कारण) या राज्य-निर्भर एन्कोडिंग के साथ किसी भी स्ट्रीम के लिए। यह प्रारंभिक पारी की स्थिति में आश्वस्त नहीं है। "

परिभाषा को इंट में बदलें ताकि त्रुटि संदेश प्रेषित हो सकें, और फिर फ़ाइल आकार का उपयोग करें 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
}

5
@mezhaka: यह CERT रिपोर्ट बस गलत है। fseekoऔर ftello(या fseekऔर ftellआप पूर्व और फ़ाइल आप के साथ काम कर सकते हैं आकार पर सीमा के साथ खुश बिना अटक कर रहे हैं) एक फ़ाइल की लंबाई निर्धारित करने के लिए सही तरीका है। stat-बेड समाधान कई "फाइलों" (जैसे ब्लॉक डिवाइसेस) पर काम नहीं करते हैं और गैर-पॉसिक्स-ईश सिस्टम के लिए पोर्टेबल नहीं हैं।
R .. GitHub STOP हेल्पिंग ICE

1
यह कई गैर-पॉज़िक्स आज्ञाकारी प्रणालियों (जैसे मेरी बहुत न्यूनतर
मैबेड

9

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 (मानक)

एएनएसआई सी सीधे रास्ते फ़ाइल की लंबाई निर्धारित करने के लिए प्रदान करता है नहीं करता है।
हमें अपने दिमाग का इस्तेमाल करना होगा। अभी के लिए, हम दृष्टिकोण का उपयोग करेंगे!

सार

  • फ़ाइल का उपयोग करके अंत तक की तलाश करें 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);
}

यदि फ़ाइल stdinया पाइप है। POSIX, ANSI C काम नहीं करेगा।
यह वापसी के लिए जा रहा होगा 0अगर फाइल एक पाइप या है stdin

राय : आपको इसके बजाय POSIX मानक का उपयोग करना चाहिए । क्योंकि, इसमें 64 बिट सपोर्ट है।


1
struct _stat64और __stat64()_Windows के लिए।
बॉब स्टीन

5

और यदि आप एक Windows ऐप बना रहे हैं, तो GetFileSizeEx API का उपयोग CRT फ़ाइल I / O के रूप में गन्दा करें, विशेष रूप से फ़ाइल की लंबाई निर्धारित करने के लिए, विभिन्न प्रणालियों पर फ़ाइल अभ्यावेदन में विशिष्टताओं के कारण;)


5

यदि आप 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;
}

24
यह मानक C नहीं है। यह POSIX मानक का हिस्सा है, लेकिन C मानक नहीं है।
डेरेक पार्क

3

Google में एक त्वरित खोज में fseek और ftell का उपयोग करने का एक तरीका मिला और इस प्रश्न के उत्तर के साथ एक धागा है कि इसे केवल दूसरे तरीके से C में नहीं किया जा सकता है।

आप NSPR की तरह पोर्टेबिलिटी लाइब्रेरी का उपयोग कर सकते हैं (लाइब्रेरी जो फ़ायरफ़ॉक्स को अधिकार देता है) या इसके कार्यान्वयन (बल्कि बालों वाली) की जांच कर सकता है।


1

मैंने फ़ाइल लंबाई खोजने के लिए कोड के इस सेट का उपयोग किया।

//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);

1

इसे इस्तेमाल करे --

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

यह पहले क्या करता है, फ़ाइल के अंत की तलाश करें; फिर, रिपोर्ट करें कि फ़ाइल पॉइंटर कहाँ है। अंत में (यह वैकल्पिक है) यह फ़ाइल की शुरुआत में वापस आ जाता है। ध्यान दें कि fpएक बाइनरी स्ट्रीम होना चाहिए।

file_size में फ़ाइल में बाइट्स की संख्या समाहित है। ध्यान दें कि चूंकि (चढ़ाई के अनुसार। H) अहस्ताक्षरित लंबा प्रकार 4294967295 बाइट्स (4 गीगाबाइट्स) तक सीमित है, यदि आपको उससे भिन्न फ़ाइलों के साथ व्यवहार करने की संभावना है, तो आपको एक भिन्न चर प्रकार खोजने की आवश्यकता होगी।


3
8 साल पहले के डेरेक के जवाब से यह कैसे अलग है ?
पीपी

यह द्विआधारी धारा के लिए अपरिभाषित व्यवहार है, और एक पाठ धारा के ftellलिए फ़ाइल से पढ़ी जा सकने वाली बाइट्स की संख्या का एक मान प्रतिनिधि वापस नहीं करता है।
एंड्रयू हेनले

0

मेरे पास एक फ़ंक्शन है जो केवल साथ काम करता है stdio.h। मुझे यह बहुत पसंद है और यह बहुत अच्छा काम करता है और बहुत संक्षिप्त है:

size_t fsize(FILE *File) {
    size_t FSZ;
    fseek(File, 0, 2);
    FSZ = ftell(File);
    rewind(File);
    return FSZ;
}

0

यहां एक सरल और साफ फ़ंक्शन है जो फ़ाइल का आकार लौटाता है।

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 
}

1
क्या आपको फ़ाइल बंद करने की आवश्यकता नहीं है?
जेरी जेरेमिया

नहीं, मैं उन कार्यों को नापसंद करता हूं जो एक मार्ग की अपेक्षा करते हैं। इसके बजाय, कृपया टीआई एक्सपेक्ट को एक फ़ाइल पॉइंटर बनाएं
श्री ऑस्कर

-3

आप फ़ाइल को खोल सकते हैं, फ़ाइल के नीचे से 0 ऑफसेट रिश्तेदार पर जाएं

#define SEEKBOTTOM   2

fseek(handle, 0, SEEKBOTTOM)  

fseek से दिया गया मान फ़ाइल का आकार है।

मैंने लंबे समय तक सी में कोड नहीं किया, लेकिन मुझे लगता है कि इसे काम करना चाहिए।


12
आपको SEEKBOTTOM जैसा कुछ परिभाषित नहीं करना चाहिए। #include <stdio.h> fseek (संभाल, 0, SEEK_END);
सिगाजिस

-4

प्रश्न को देखते हुए, ftellआसानी से बाइट्स की संख्या प्राप्त कर सकते हैं।

  long size = ftell(FILENAME);
  printf("total size is %ld bytes",size);

ftellएक फ़ाइल डिस्क्रिप्टर की अपेक्षा करता है, न कि एक फ़ाइलनाम, तर्क के रूप में।
बमर

@ बरमार, नहीं, ftellएक फ़ाइल डिस्क्रिप्टर की अपेक्षा नहीं करता है, यह एक FILE*बदले की अपेक्षा करता है । पहले मैन पेज देखें!

दृष्टिकोण पूरी तरह से गलत है, यह स्थिर है जो हर समय ftellवापस आ जाएगा 0!

यह उत्तर गलत है, जैसा कि एक के लिए है, आपको fseek()फ़ाइल के अंत की तलाश करने के लिए सबसे पहले उपयोग करने की आवश्यकता है , और यह भी ftell()उम्मीद है कि FILE *, स्ट्रिंग नहीं! आप अपने जवाब को भली भाँति परोसेंगे।
श्री ऑस्कर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.