InfluentialAudio
InfluentialAudio

Reputation: 13

fgets not reading the beginning of a line

I am having trouble reading a few lines of text from a file using fgets. The file is some basic user data that is written to a file within the bundle the first time the plugin is launched. Any subsequent launch of the plugin should result in the user data being read and cross referenced to check the users authenticity.

The data is always 3 lines long and is written with frwite exactly as it should be and is opened with fopen.

My original theory was to just call fgets 3 times reading each line into it's own char array which is part of a data struct. The problem is the first line is read correctly, the second line is read as though the position indicator starts on the next line but offset by the number of characters read from line 1. The third line is then not read at all.

fgets is not returning any errors and is behaving as though it has read the data it should have so i'm obviously missing something.

Anyway here's a portion of my code hopefully someone can some shed some light on my mistakes!

int length;

fgets(var.n, 128, regFile);
length = strlen(var.n);
var.n[length-1] = NULL;

fgets(var.em, 128, regFile);
length = strlen(var.em);
var.em[length-1] = NULL;

fgets(var.k, 128, regFile);
length = strlen(var.k);
var.k[length-1] = NULL;

fclose(regFile);

Setting the last character in each string to NULL is just to remove the /n

This sequence of code outputs the whole of line 1, the second half of line 2 and none of line 3.

Upvotes: 0

Views: 1225

Answers (2)

alvits
alvits

Reputation: 6758

In POSIX systems, including Linux, there is no differentiation between binary and text files. When opening a file stream, the b flag is ignored. This is described in fopen().

You might ask "how would you differentiate text from binary files?". The contents differentiate them. How the contents are written makes them a binary or text file.

Look at the signature size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream). You'll notice that it writes the contents of *ptr with size describing the size of each members, nmemb. The written stream is not converted to string. If you were to write 97 it will write the binary 97 which in ascii is A. Binary data does not obey string terminations. Presence of \n and \0 in data is literally written as is.

Now look at the signature int fputs(const char *s, FILE *stream). It writes the string content of *s. If you were to write 97, it will have to be a string "97" which is not A. String termination is obeyed. \n is automatically converted to the O/S supported newline (CRLF or LF).

You can coerce fwrite() to behave like fputs() but not the other way around. For example, if you declare ptr as a pointer to string and calculate the size exactly as the length of the content excluding string terminator, you'll be able to write it out as text instead of binary. You will also need to handle \0 and \n and convert them to O/S supported newline. Writing the entire string buffer will write everything including and past the string terminators.

Upvotes: 0

InfluentialAudio
InfluentialAudio

Reputation: 13

Thanks to @alvits for the answer to this one:

fwrite() is not compatible with fgets(). Files created using fwrite() should use fread() to read them ?>back in. Both fwrite() and fread() operates on binary streams unless explicitly converted to and from >strings. fgets() is compatible with fputs(), both operates on strings.

I used fputs() to write my data instead and it read back in perfectly.

Upvotes: 1

Related Questions