সি তে, আমি কীভাবে একটি পাঠ্য ফাইল পড়ি এবং সমস্ত স্ট্রিং প্রিন্ট করব


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


সি / সি ++ এ ফাইলটি না খোলায় ফাইল থেকে ডেটা পড়া সম্ভব?
সাগর প্যাটেল

যদি পাঠ্য ফাইলটিতে কমা দ্বারা পৃথক পূর্ণসংখ্যার মান থাকে? কোডটি কী হবে তার থেকেও আপনি নিজের উত্তরটি এতে সম্পাদন করতে পারবেন।
মহসিন

উপরেরটি কোনও ধরণের পাঠ্য ফাইলের জন্য কাজ করে। আপনি যদি কোনও সিএসভি ফাইল থেকে নম্বরগুলি বিশ্লেষণ করতে চান তবে এটি একটি ভিন্ন সমস্যা।
অলোক সিংহল

4
@ সার্বভৌম বিনিময় প্রশ্নটি লাইন সম্পর্কে কথা বলবে না - এটি কোনও ফাইল পড়া এবং এর বিষয়বস্তু অনুলিপি করা সম্পর্কে stdout
অলোক সিংহল

4
@ শেজেফ একটি ফাইলের মধ্যে ইওফ অক্ষর থাকতে পারে না। মনে রাখবেন যে 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;
}

এটি দরকারী কিনা তা আমাকে জানান বা আপনি এটি থেকে কিছু শিখতে পারেন :)


4
এর buffer[string_size] = '\0';বদলে পড়া উচিত নয় string_size+1? আমি যতদূর জানি প্রকৃত স্ট্রিং থেকে যায় 0কাছে string_size-1এবং \0চরিত্র এইভাবে এ করা প্রয়োজন string_size, ঠিক?
apssil0n

4
কোনও ফাইলের আকার ব্যবহার করা ftellএবং fseekএটি অনিরাপদ: সুরক্ষিত কোডিং.সেট.আর
জোয়াকিম

4
এই কোডটিতে একটি মেমরি ফুটো রয়েছে, আপনি কখনও ফাইলটি বন্ধ করেন না। একটি নিখোঁজ রয়েছেfclose(handle)
জোয়াকিম

4
একটি টাইপো আছে যেখানে আপনি fclose (হ্যান্ডেল) বলছেন, এটি fclose (হ্যান্ডলার) হওয়া উচিত
এডুয়ার্ডো কোবুচি

4
আপনি ব্যবহার করতে পারে 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

পরিবর্তে "পড়ুন ()" ব্যবহার করুন ও fscanf:

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

বর্ণনা

পঠন () ফাংশনটি nbyteওপেন ফাইল বর্ণনাকারীর সাথে যুক্ত ফাইল থেকে fildesবাইটারে নির্দেশিত বাফারে পড়ার চেষ্টা করবে buf

এখানে একটি উদাহরণ:

http://cmaological.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);

একটি বিকল্প পদ্ধতির ব্যবহার করা getc/ putcএকটি সময়ে পড়তে / লেখা 1 গৃহস্থালির কাজ। অনেক কম দক্ষ। একটি ভাল উদাহরণ: http://www.eskimo.com/~scs/cclass/notes/sx13.html


readআপনাকে একটি নির্দিষ্ট সংখ্যক অক্ষর পড়তে দেবে। আপনার বাফারটি পূরণ করার জন্য পর্যাপ্ত পরিমাণে পড়ুন, তারপরে আপনার বাফারটিকে স্ক্রিনে ফেলে দিন, এটি পরিষ্কার করুন এবং আপনি ফাইলটির শেষে না আসা পর্যন্ত পুনরাবৃত্তি করুন।
বিটিএ

1

দুটি পদ্ধতির মনে লাফিয়ে যায়।

প্রথম, ব্যবহার করবেন না scanf। ব্যবহারের fgets()যা বাফারের আকার নির্দিষ্ট করার একটি প্যারামিটার নেয়, এবং যা কোনো সম্পর্কে newline অক্ষর অক্ষত ছেড়ে। বাফারের সামগ্রীতে মুদ্রিত হওয়া ফাইলটির একটি সাধারণ লুপ স্বাভাবিকভাবেই ফাইলটি অক্ষত রাখতে হবে।

দ্বিতীয়ত, ব্যবহার করুন fread()বা সাধারণ সি আইডিয়ামের সাথে fgetc()। এগুলি একসাথে স্থির আকারের অংশ বা একক অক্ষরে ফাইলটি প্রক্রিয়া করবে।

যদি আপনার অবশ্যই সাদা-স্পেসের সীমানাযুক্ত স্ট্রিংগুলির মাধ্যমে ফাইলটি প্রক্রিয়া করতে হয় তবে ফাইলটি পড়তে fgetsবা freadপড়তে ব্যবহার করুন এবং strtokহোয়াইটস্পেসে বাফারকে আলাদা করতে পছন্দ করুন something আপনার লক্ষ্যযুক্ত স্ট্রিংগুলি বাফার সীমানাটি বিস্তৃত হওয়ার সম্ভাবনা রয়েছে বলে এক বাফার থেকে অন্যটিতে স্থানান্তরকে হ্যান্ডেল করতে ভুলবেন না।

যদি 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;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.