🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

fread issue

Started by
10 comments, last by AbandonedAccount 17 years, 10 months ago
When I open a file in text mode, and I get the size of that file, the size is wrong if my text in on multiple lines. The following piece of code causes fread to be unable to read the file if the text in the file is on multiple lines.

FILE *file = fopen(filename, "rt");
if(file) {
  fseek(file, 0, SEEK_END); 
  unsigned int size = ftell(file); 
  fseek(file, 0, SEEK_SET); 
  if(!fread(filebuff, size, 1, file)) {
    fclose(file);
    return;
  }
  fclose(file);
}


The size variable is correct and reflects the real size of my file. I am aware that in some circumstances, a text editor adds a '\r' to the '\n'. Actually, I am guessing that this is my error; counting all my caracters (including '\n') in my file = size + numlines('\r'). How do you read an entire text file into a buffer ?
Advertisement
<bump>
doesnt seek_set zero result in no change in the file pointer.


typically you use seek_set to move back from a point by a few places.

fseek(file, -5, SEEK_SET), moves back 5 bytes from your current pointer.


so in your code, your seeking zero places from the end (which is the end!), because you moved to it before the ftell..



you should do fseek(file,0, SEEK_BEGIN); to get back to the start.
According to the MSDN documentation:

SEEK_CUR Current position of file pointer.
SEEK_END End of file.
SEEK_SET Beginning of file.

I just validated that the documentation is correct. SEEK_BEGIN doesn't seem to even exists. Anyway, that doesn't seem to be the source of my error, when everything is on a single line, the buffer is filled correctly with the text included in my file.
I don't know if this is relevant, but I think your fread args are the wrong way round.

fread(buf,sizeof(char),num,fp);

Shouldn't make a difference but worth a try. I can't see any other reason why your code is failing. In what way is it failing? What does fread return? What is in the buffer after the fread call?

Assuming you have a good reason for using C-style file io, you could always do this:

char buf[MAX];void f(){    FILE *fp=fopen("file.txt","r");    char *b=buf;    int c=fgetc(fp);    while(c!=EOF && b-buf<MAX-1)        {        *b++=c; c=fgetc(fp);        }    fclose(fp); *b=0;}
I'll give it a try ... but the arguments are :

size_t fread(
void *buffer,
size_t size,
size_t count,
FILE *stream
);

With what you are suggesting me, I might receive a success from fread when it actually reads only half of my file.
When I was Googling fread just now, I found this page. At the bottom is a code snippet purporting to read in a text file using the C style file io functions. Maybe worth a look.

I note that even though it is reading a .txt file, they still open the stream in binary mode. Not sure how this is relevant but again, worth a try.
In this example, they are reading the file in "rb" mode ... even though the file is actually a text file.

This works ... I'll use that ... I just thought that reading in text mode might have a use.

Thanks
Using seek's when your file was opened as a textfile doesn't
work, has sth to do with newline/carriage return..

There should be more info in the msdn.


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_fseek.asp

For streams opened in text mode, fseek has limited use, because carriage return–linefeed translations can cause fseek to produce unexpected results. The only fseek operations guaranteed to work on streams opened in text mode are:
visit my website at www.kalmiya.com
You must distinguish between the type of the file, the mode in which the file is opened, and the type of the reading operation. The program has no idea what the actual file type is - it's just a sequence of bytes. The binary-reading operations (fread, etc.) are meant to be used on files that were opened in binary mode, even if they "are text files" - whatever that means. You can try using them on files opened in text mode, but you have to be aware of the fact that text mode causes some stuff to be translated. Thus, you'll still get the size of the actual file on disk in bytes when you futz around with fseek and ftell, but the number of bytes you will *read* from the file will be less, because of (a) CR/LF conversion; (b) the EOF character (ascii 26 on dos/windows, 4 on unix/linux). Normally you don't want this.

However, if the file really "is a text file", then chances are very high that you want to open it in text mode *and use text-reading operations*, such as sscanf().

Of course, C++ has some much nicer functionality available, but it still draws all the same text-vs.-binary distinctions.

This topic is closed to new replies.

Advertisement