By Richard


2010-08-11 22:40:34 8 Comments

I have a text file named test.txt

I want to write a C program that can read this file and print the content to the console (assume the file contains only ASCII text).

I don't know how to get the size of my string variable. Like this:

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

The size 999 doesn't work because the string returned by fscanf can be larger than that. How can I solve this?

8 comments

@Edu 2010-08-11 22:59:54

You can use fgets and limit the size of the read string.

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

You can change the while in your code to:

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

@Odin 2018-08-14 17:45:44

#include <stdio.h>
#include <stdlib.h>
int main() {

int num;
FILE *fptr; 



if ((fptr = fopen("/root/Desktop/my_pass.txt","r")) == NULL) {       // checks if file exists
    puts("File not exists");
    exit(1);                    // for exit(1) is required #include <stdlib.h> 
} else 

fscanf(fptr,"%d", &num);                

printf("My pass is:  %d\n", num);           
fclose(fptr); 

return 0;
}

@lfzawacki 2010-08-12 03:56:43

There are plenty of good answers here about reading it in chunks, I'm just gonna show you a little trick that reads all the content at once to a buffer and prints it.

I'm not saying it's better. It's not, and as Ricardo sometimes it can be bad, but I find it's a nice solution for the simple cases.

I sprinkled it with comments because there's a lot going on.

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

Let me know if it's useful or you could learn something from it :)

@aepsil0n 2014-06-03 09:54:26

Shouldn't it read buffer[string_size] = '\0'; instead of string_size+1? Afaik the actual string goes from 0 to string_size-1 and the \0 character thus needs to be at string_size, right?

@lfzawacki 2014-06-04 04:48:12

You're right, I corrected it. This answer has been here for quite some time and this issue went unnoticed, gotta love C :)

@aepsil0n 2014-06-04 14:37:38

Yep, that's a bit odd… I had to ran into a segfault until I noticed. C just way too low-level for my taste.

@Joakim 2014-07-01 09:05:05

Using ftell and fseek to find the size of a file is unsafe: securecoding.cert.org/confluence/display/seccode/…

@vexe 2015-09-07 00:45:34

One thing to note on Windows, string_size might not be equal to read_size if the file is opened in text mode. I quote from this link (bytes.com/topic/c/answers/479976-interesting-thing-about-fr‌​ead) Under Windows, a text file has two characters for end-of-line (CR+LF -- "\r\n"), but the C library will strip the CR when reading a file open in text mode, so that the program will only see LF ('\n'). The stat() call is returning the "real" size if the file, while the returns from fread() have stripped the CR.

@vexe 2015-09-07 13:31:07

@Joakim 2016-04-10 22:16:08

This code contains a memory leak, you never close the file. There is a missing fclose(handle)

@Eduardo Cobuci 2016-09-21 17:41:41

There is a typo where you call fclose(handle), it should be fclose(handler)

@overexchange 2017-01-02 03:17:26

Your approach of reading file looks better than accepted answer. But buffer can be too large to handle. Is it practical to allocate a file size buffer? Despite this answer supports it

@Jevgenij Kononov 2017-12-20 15:22:15

It is really strange, string_size and read_size for me always not equal. I tried update this functions with different logic statements but I am always getting incorrect read and string sizes.

@The_Androctonus 2018-02-07 07:55:53

You could use calloc(2) rather than malloc(1) to skip having to set the null terminator.

@Sagar Shah 2013-08-23 12:31:16

Instead just directly print the characters onto the console because the text file maybe very large and you may require a lot of memory.

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

@Alok Singhal 2010-08-12 00:03:45

The simplest way is to read a character, and print it right after reading:

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

c is int above, since EOF is a negative number, and a plain char may be unsigned.

If you want to read the file in chunks, but without dynamic memory allocation, you can do:

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

The second method above is essentially how you will read a file with a dynamically allocated array:

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 */
}

Your method of fscanf() with %s as format loses information about whitespace in the file, so it is not exactly copying a file to stdout.

@Sagar Patel 2015-10-27 11:13:31

It is possible to read data from file without opening that file in c/c++??

@Mohsin 2016-10-21 20:43:52

what if the the text file contains comma separated integer values? than what would be the code can you edit your answer with that too in it.

@Alok Singhal 2016-10-22 03:34:36

The above works for any kind of text file. If you want to parse the numbers from a CSV file, that's a different problem.

@overexchange 2017-01-02 03:14:10

How do you know that every line is 1024 bytes? Ideally your code should convey an approach that every line is read. You are reading in terms of bytes and nothing more

@Alok Singhal 2017-01-03 03:35:10

@overexchange The question doesn't talk about lines - it is about reading a file and copying its contents to stdout.

@delive 2017-05-18 08:23:02

This is the best and correct method to read ( primitive ). if you want had a best code, in the CHUNK can you assign size from file.

@shjeff 2017-11-22 11:58:18

while ((c = getc(file)) != EOF) - what if file contains EOF character?

@Alok Singhal 2017-11-22 22:14:36

@shjeff A file cannot contain EOF character. Note that c is int, and C will guarantee that EOF is not equal to any valid character.

@Alok Singhal 2017-11-22 22:16:54

@shjeff see stackoverflow.com/a/13694450 for example.

@shjeff 2017-11-24 12:50:45

@AlokSinghal, ok - I see you're right. I had same issue as in link you pointed, so I asked about this.

@rigon 2010-08-11 23:17:52

You could read the entire file with dynamic memory allocation, but isn't a good idea because if the file is too big, you could have memory problems.

So is better read short parts of the file and print it.

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

@DVK 2010-08-11 22:57:44

Use "read()" instead o fscanf:

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

DESCRIPTION

The read() function shall attempt to read nbyte bytes from the file associated with the open file descriptor, fildes, into the buffer pointed to by buf.

Here is an example:

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

Working part from that example:

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

An alternate approach is to use getc/putc to read/write 1 char at a time. A lot less efficient. A good example: http://www.eskimo.com/~scs/cclass/notes/sx13.html

@bta 2010-08-11 23:00:49

read will let you read in a certain number of characters. Read in enough to fill your buffer, then dump your buffer to the screen, clear it out, and repeat until you get to the end of the file.

@RBerteig 2010-08-11 23:03:23

Two approaches leap to mind.

First, don't use scanf. Use fgets() which takes a parameter to specify the buffer size, and which leaves any newline characters intact. A simple loop over the file that prints the buffer content should naturally copy the file intact.

Second, use fread() or the common C idiom with fgetc(). These would process the file in fixed-size chunks or a single character at a time.

If you must process the file over white-space delimited strings, then use either fgets or fread to read the file, and something like strtok to split the buffer at whitespace. Don't forget to handle the transition from one buffer to the next, since your target strings are likely to span the buffer boundary.

If there is an external requirement to use scanf to do the reading, then limit the length of the string it might read with a precision field in the format specifier. In your case with a 999 byte buffer, then say scanf("%998s", str); which will write at most 998 characters to the buffer leaving room for the nul terminator. If single strings longer than your buffer are allowed, then you would have to process them in two pieces. If not, you have an opportunity to tell the user about an error politely without creating a buffer overflow security hole.

Regardless, always validate the return values and think about how to handle bad, malicious, or just malformed input.

Related Questions

Sponsored Content

15 Answered Questions

[SOLVED] How do I copy a file in Python?

42 Answered Questions

[SOLVED] How do I check whether a file exists without exceptions?

54 Answered Questions

[SOLVED] How do I include a JavaScript file in another JavaScript file?

34 Answered Questions

[SOLVED] How to read a file line-by-line into a list?

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

22 Answered Questions

[SOLVED] How do I save a String to a text file using Java?

33 Answered Questions

[SOLVED] How do I create a Java string from the contents of a file?

9 Answered Questions

[SOLVED] How do you append to a file in Python?

  • 2011-01-16 16:20:33
  • user502039
  • 1378762 View
  • 1317 Score
  • 9 Answer
  • Tags:   python file append

31 Answered Questions

[SOLVED] How to read all files in a folder from Java?

  • 2009-12-04 03:39:37
  • M.J.
  • 900821 View
  • 572 Score
  • 31 Answer
  • Tags:   java file io folder

18 Answered Questions

[SOLVED] Why should text files end with a newline?

Sponsored Content