सी में, मुझे एक टेक्स्ट फाइल कैसे पढ़नी चाहिए और सभी स्ट्रिंग्स को प्रिंट करना चाहिए


94

मेरे पास एक टेक्स्ट फ़ाइल है जिसका नाम है test.txt

मैं एक सी प्रोग्राम लिखना चाहता हूं जो इस फाइल को पढ़ सके और कंटेंट को कंसोल पर प्रिंट कर सके (मान लें कि फाइल में केवल ASCII टेक्स्ट है)।

मुझे नहीं पता कि मेरे स्ट्रिंग चर का आकार कैसे प्राप्त करें। इस कदर:

char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
    while (fscanf(file, "%s", str)!=EOF)
        printf("%s",str);
    fclose(file);
}

आकार 999काम नहीं करता है क्योंकि स्ट्रिंग द्वारा लौटा गया fscanfउससे बड़ा हो सकता है। इसे कैसे हल किया जा सकता है?

जवाबों:


134

सबसे आसान तरीका है कि किसी पात्र को पढ़ें, और पढ़ने के बाद उसे सही तरीके से प्रिंट करें:

int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
    while ((c = getc(file)) != EOF)
        putchar(c);
    fclose(file);
}

cहै intके बाद से, ऊपर EOFएक नकारात्मक संख्या है, और एक सादा charहो सकता है unsigned

यदि आप फ़ाइल को चंक्स में पढ़ना चाहते हैं, लेकिन गतिशील मेमोरी आवंटन के बिना, आप कर सकते हैं:

#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;

file = fopen("test.txt", "r");
if (file) {
    while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
        fwrite(buf, 1, nread, stdout);
    if (ferror(file)) {
        /* deal with error */
    }
    fclose(file);
}

उपरोक्त दूसरी विधि अनिवार्य रूप से है कि आप एक फ़ाइल को डायनामिक रूप से आवंटित सरणी के साथ कैसे पढ़ेंगे:

char *buf = malloc(chunk);

if (buf == NULL) {
    /* deal with malloc() failure */
}

/* otherwise do this.  Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
    /* as above */
}

प्रारूप के fscanf()साथ आपका तरीका %sफ़ाइल में व्हॉट्सएप के बारे में जानकारी खो देता है, इसलिए यह फ़ाइल की प्रतिलिपि बिल्कुल नहीं बना रहा है stdout


उस फ़ाइल को c / c ++ में खोले बिना फ़ाइल से डेटा पढ़ना संभव है ??
सागर पटेल

क्या होगा यदि पाठ फ़ाइल में अल्पविराम से अलग पूर्णांक मान हैं? कोड क्या होगा इससे आप अपने उत्तर को उसमें भी संपादित कर सकते हैं।
मोहसिन

उपरोक्त किसी भी प्रकार की टेक्स्ट फ़ाइल के लिए काम करता है। यदि आप CSV फ़ाइल से संख्याओं को पार्स करना चाहते हैं, तो यह एक अलग समस्या है।
आलोक सिंघल

1
@overexchange सवाल लाइनों के बारे में बात नहीं करता है - यह किसी फ़ाइल को पढ़ने और उसकी सामग्री को कॉपी करने के बारे में है stdout
आलोक सिंघल

1
@ शशि ए फ़ाइल में EOF वर्ण नहीं हो सकता। ध्यान दें कि cint है, और C गारंटी देगा कि EOFकिसी भी मान्य वर्ण के बराबर नहीं है।
आलोक सिंघल

60

यहाँ बहुत सारे अच्छे उत्तर दिए गए हैं, इसे चंक्स में पढ़ने के बारे में, मैं आपको बस एक छोटी सी चाल दिखाने जा रहा हूँ जो एक बार में सभी सामग्री को पढ़ता है और उसे प्रिंट करता है।

मैं यह नहीं कह रहा हूं कि यह बेहतर है। यह नहीं है, और रिकार्डो के रूप में कभी-कभी यह खराब हो सकता है, लेकिन मुझे लगता है कि यह सरल मामलों के लिए एक अच्छा समाधान है।

मैंने इसे टिप्पणियों के साथ छिड़का क्योंकि वहाँ बहुत कुछ चल रहा है।

#include <stdio.h>
#include <stdlib.h>

char* ReadFile(char *filename)
{
   char *buffer = NULL;
   int string_size, read_size;
   FILE *handler = fopen(filename, "r");

   if (handler)
   {
       // Seek the last byte of the file
       fseek(handler, 0, SEEK_END);
       // Offset from the first to the last byte, or in other words, filesize
       string_size = ftell(handler);
       // go back to the start of the file
       rewind(handler);

       // Allocate a string that can hold it all
       buffer = (char*) malloc(sizeof(char) * (string_size + 1) );

       // Read it all in one operation
       read_size = fread(buffer, sizeof(char), string_size, handler);

       // fread doesn't set it so put a \0 in the last position
       // and buffer is now officially a string
       buffer[string_size] = '\0';

       if (string_size != read_size)
       {
           // Something went wrong, throw away the memory and set
           // the buffer to NULL
           free(buffer);
           buffer = NULL;
       }

       // Always remember to close the file.
       fclose(handler);
    }

    return buffer;
}

int main()
{
    char *string = ReadFile("yourfile.txt");
    if (string)
    {
        puts(string);
        free(string);
    }

    return 0;
}

मुझे बताएं कि क्या यह उपयोगी है या आप इससे कुछ सीख सकते हैं :)


2
buffer[string_size] = '\0';इसके बजाय पढ़ना नहीं चाहिए string_size+1? Afaik वास्तविक स्ट्रिंग से जाता 0है string_size-1और \0चरित्र इस प्रकार string_sizeसही होने की आवश्यकता है ?
apsil0n

4
फ़ाइल के आकार का उपयोग करना ftellऔर fseekउसका पता लगाना असुरक्षित है: Securecoding.cert.org/confluence/display/seccode/…
जोकिम

1
इस कोड में एक मेमोरी रिसाव होता है, आप फ़ाइल को कभी बंद नहीं करते हैं। एक लापता हैfclose(handle)
जोकिम

1
एक टाइपो है जहां आप फेकलोज (हैंडल) कहते हैं, यह
फेकलोज

3
आप नल टर्मिनेटर सेट करने के लिए छोड़ देने के calloc(2)बजाय उपयोग कर सकते हैं malloc(1)

14

इसके बजाय सीधे वर्णों को कंसोल पर प्रिंट करें क्योंकि पाठ फ़ाइल शायद बहुत बड़ी है और आपको बहुत अधिक मेमोरी की आवश्यकता हो सकती है।

#include <stdio.h>
#include <stdlib.h>

int main() {

    FILE *f;
    char c;
    f=fopen("test.txt","rt");

    while((c=fgetc(f))!=EOF){
        printf("%c",c);
    }

    fclose(f);
    return 0;
}

6

O fscanf के बजाय "रीड ()" का उपयोग करें:

ssize_t read(int fildes, void *buf, size_t nbyte);

विवरण

रीड () फ़ंक्शन द्वारा बताए गए बफर में nbyteओपन फाइल डिस्क्रिप्टर से जुड़ी फाइल से बाइट्स पढ़ने का प्रयास करेगा ।fildesbuf

यहाँ एक उदाहरण है:

http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html

उस उदाहरण से कार्य करने वाला भाग:

f=open(argv[1],O_RDONLY);
while ((n=read(f,l,80)) > 0)
    write(1,l,n);

एक वैकल्पिक दृष्टिकोण एक बार में 1 वर्ण को पढ़ने / लिखने के लिए getc/ उपयोग putcकरना है। बहुत कम कुशल। एक अच्छा उदाहरण: http://www.eskimo.com/~scs/cclass/notes/sx13.html


readआपको कुछ निश्चित वर्णों में पढ़ने देगा। अपने बफ़र को भरने के लिए पर्याप्त रूप से पढ़ें, फिर अपने बफ़र को स्क्रीन पर डंप करें, इसे खाली करें, और फ़ाइल के अंत तक दोहराएं।
23

1

दो दृष्टिकोण मन को छलांग देते हैं।

सबसे पहले, उपयोग न करें scanffgets()बफर आकार को निर्दिष्ट करने के लिए एक पैरामीटर का उपयोग करें , और जो किसी भी newline वर्ण को बरकरार रखता है। बफर सामग्री को प्रिंट करने वाली फ़ाइल पर एक साधारण लूप स्वाभाविक रूप से फ़ाइल को कॉपी करना चाहिए।

दूसरा, उपयोग fread()या आम सी मुहावरे के साथ fgetc()। ये फ़ाइल को एक बार में निश्चित आकार के टुकड़े या एकल वर्ण में संसाधित करेंगे।

यदि आपको फ़ाइल को व्हाइट-स्पेस सीमांकित स्ट्रिंग्स पर संसाधित करना होगा, तो fgetsया तो freadफ़ाइल को पढ़ने के लिए उपयोग करें, और strtokव्हाट्सएप पर बफर को विभाजित करने के लिए कुछ पसंद करें। संक्रमण को एक बफ़र से दूसरे पर हैंडल करना न भूलें, क्योंकि आपके टारगेट स्ट्रिंग्स बफर बाउंड्री को फैलाने की संभावना रखते हैं।

यदि scanfरीडिंग करने के लिए उपयोग करने के लिए बाहरी आवश्यकता है , तो स्ट्रिंग की लंबाई को सीमित कर सकते हैं जो प्रारूप विनिर्देशक में एक सटीक फ़ील्ड के साथ पढ़ सकती है। 999 बाइट बफर के साथ आपके मामले में, फिर कहें कि scanf("%998s", str);जो सबसे अधिक 998 वर्णों को शून्य टर्मिनेटर के लिए बफर छोड़ने वाले कमरे में लिखेंगे। यदि आपके बफर की तुलना में लंबे समय तक एकल तार की अनुमति है, तो आपको उन्हें दो टुकड़ों में संसाधित करना होगा। यदि नहीं, तो आपके पास बफर ओवरफ्लो सुरक्षा छेद बनाए बिना उपयोगकर्ता को विनम्रतापूर्वक त्रुटि के बारे में बताने का अवसर है।

भले ही, हमेशा रिटर्न मानों को मान्य करें और सोचें कि खराब, दुर्भावनापूर्ण, या सिर्फ विकृत इनपुट से कैसे निपटें।


1

आप fgetsपढ़े गए स्ट्रिंग के आकार का उपयोग और सीमित कर सकते हैं ।

char *fgets(char *str, int num, FILE *stream);

आप whileअपने कोड को इसमें बदल सकते हैं :

while (fgets(str, 100, file)) /* printf("%s", str) */;

0

आप संपूर्ण फ़ाइल को डायनामिक मेमोरी आवंटन के साथ पढ़ सकते हैं, लेकिन यह एक अच्छा विचार नहीं है क्योंकि यदि फ़ाइल बहुत बड़ी है, तो आपको मेमोरी समस्याएं हो सकती हैं।

तो बेहतर है कि फाइल के छोटे हिस्सों को पढ़ें और उसे प्रिंट करें।

#include <stdio.h>
#define BLOCK   1000

int main() {
    FILE *f=fopen("teste.txt","r");
    int size;
    char buffer[BLOCK];
    // ...
    while((size=fread(buffer,BLOCK,sizeof(char),f)>0)
            fwrite(buffer,size,sizeof(char),stdout);
    fclose(f);
    // ...
    return 0;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.