Is it possible to read a whole file at once with text files, or can I only use fgets and is that the most data I can fetch at any time? (fread() doesn't work on text files, I've experienced and then been told ;-)).

Thanks in advance,

PS: And suppose I use fseek, ftell, to get the filesize of a file, is that size+1 the correct size for the buffer to read in the complete file using series of fgets calls?

Recommended Answers

All 9 Replies

>fread() doesn't work on text files, I've experienced and then been told ;-)
Whoever told you that is wrong. fread works fine on text streams.

>suppose I use fseek, ftell, to get the filesize of a file, is that size+1 the correct
>size for the buffer to read in the complete file using series of fgets calls?
The practical answer is yes, the size you get should be sufficient. The complete answer is that this solution is non-portable and not guaranteed to work. A better solution is to build a dynamic array or linked list of strings that can grow as you read the file.

How would one use fread() then with a text file, considering you can't determine the size fread will read?

>considering you can't determine the size fread will read?
How do you figure that? You determine the size fread will read the same way you determine the size fgets will read: by specifying it based on the buffer size. And just as with fgets, you can use fread to load the file in chunks rather than all at once:

#include <stdio.h>

int main ( void )
{
  FILE *in = fopen ( "test.txt", "r" );

  for ( ; ; ) {
    char buf[5];
    size_t n = fread ( buf, 1, 4, in );

    // fread doesn't append '\0'
    buf[n] = '\0';
    puts ( buf );

    if ( n < 4 )
      break;
  }

  return 0;
}

Hmz.. I remember using fread() on a none-binary file, passing the fileSize (in the count and size parameters of course) and it read almost everything okay, but it messed up the last few lines: the last few lines were repeating lines from, say, 20 lines above that, somewhat like this:

m
o
n
k
e
y

k

e

y

You never had that?

I'm on Windows XP x64, using the latest version of MinGW GCC.

PS: Basically asking if fread() didn't go bananas when you passed it a size bigger than fileSize, on Windows and Linux.

>Hmz.. I remember using fread() on a none-binary file[...]
Let me put it this way: if you had problems using fread, you used fread incorrectly. Post the code that you had problems with and I'll tell you what you did wrong, but comparing notes with other people that did it wrong isn't going to help you much.

> Is it possible to read a whole file at once with text files
Are you going to write some code to stop your machine grinding to a halt if someone attempts to load an especially large file (either accidentally, or on purpose).

Or put another way, what are you going to do with this file once you've loaded it?

Narue: It's somewhere on this board, let me look it up. Edit: found it:
http://www.daniweb.com/forums/thread137672.html

Code:

int fileSize = 0;
  int n, i, j;
  printf("Opening file: \"%s\"\n", loc);

  FILE *pFile = fopen(loc, "r");
  if(pFile == NULL){
      dbgError("fopen()");
      exit(1);
  }

  fseek(pFile, 0, SEEK_END);
  fileSize = ftell(pFile);
  rewind(pFile);

  char *data = (char*) calloc(sizeof(char), fileSize + 20);

  fread(data, 1, fileSize, pFile);
  if(ferror(pFile)){
      dbgError("fread()");
      exit(1);
  }
  puts(data);

  fclose(pFile);

  printf("Done reading, parsing file now.\n");
  /*You can return here, the "wrong" data is now written to stdout*/
  return 123;

On the second page of the thread is a small testing program and some results showing that I only had the problem using fread() on "text" opened files, not on binary opened ones.

Salem: I didn't build any security in it. I'd have to make assumptions about available RAM, etc. etc. If the user is "stupid" enough to load a 2GB file when having 512MB RAM, so be it. The likeliness of that happening is small however: it reads HTMLs. But thanks for your concern nonetheless.

Remembering about that other thread, I thought you finally understood that if you are going to use fread() you need to open the file in binary mode.

FILE *pFile = fopen(loc, "rb");

Furthermore, perhaps due to your familiarity with C++ you are using that language syntax for C and it is not correct if you are not using a compiler that support C99.

All the variables need to be declared in the beginning of the block. Which would make those statements incorrect.

FILE *pFile = fopen(loc, "r");
char *data = (char*) calloc(sizeof(char), fileSize + 20);

On the second page of the thread is a small testing program and some results showing that I only had the problem using fread() on "text" opened files, not on binary opened ones.

You obviously missed Narue's answer to this problem:

size_t n = fread ( buf, 1, 4, in );

[B]    // fread doesn't append '\0'
    buf[n] = '\0';[/B]
    puts ( buf );
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.