Reputation: 61
I need to know how to read a string from a binary file using fread ().
Thing is, as I understand, if I want to copy the value of some string to a new string declared like this:
char *string;
I need to calculate first the length of the other string using strlen (), use that value to reserve memory for my new string with malloc, and then copy the value o the other string to my new string using strcpy ()
Kinda like this:
newLength = strlen ( otherString ) + 1;
string = malloc ( sizeof ( char ) * newLength );
if ( string == NULL ) {
return ( FALSE )
}
But what happens if I am reading data from a binary file, and I am trying to read a string from said file but I don't know beforehand its length, therefore I can't use malloc to reserve memory for said string?
Would this work, even though I haven't reserved memory for the string yet (I am not so convinced)?:
fread ( string, sizeof ( char ), strlen ( string ), currentFile );
I am kinda stuck now. Hopefully you guys can shed me some light and guide me a bit.
Upvotes: 1
Views: 8545
Reputation: 154085
To read a string from a file is tricky because many users call a "line of text" (various char
followed by a '\n
') a "string". But in C a "string" is various char
followed by a '\0'
.
fgets()
, scanf()
and fread()
are ill equipped to read a C string from a file. None easily have the ability to read until '\0'
.
Assuming you want to read an arbitrarily long "C string": suggest using fgetc()
.
char *ReadString(FILE *inf) {
if (inf == NULL)
return NULL;
size_t size = 1;
char *buf = malloc(size);
if (buf == NULL) {
return Handle_AllocFailure();
}
size_t i = 0;
int ch;
while ((ch = fgetc(inf)) != EOF && ch != '\0') {
if (i + 1 >= size) {
size_t newsize = (size + 1) * 4 - 1;
char *newbuf = realloc(buf, newsize);
if (newbuf == NULL) {
return Handle_AllocFailure();
}
buf = newbuf;
size = newsize;
}
buf[i++] = ch;
}
buf[i++] = '\0';
// If a final re-size is desired...
char *newbuf = realloc(buf, i);
if (newbuf == NULL) {
return Handle_AllocFailure();
}
buf = newbuf;
return buf;
}
FILE *inf;
...
char *buf = ReadString(inf);
...
free(buf);
Upvotes: 0
Reputation: 124
Your question has some mixed content. You say 'binary' file, and yet you want to read string data from it. Parsing strings from a file generally implies that the file is textual in nature. Nevertheless, without knowing a priori, the length of the string you're reading, you can read the file byte-by-byte, counting bytes until you reach a string terminator, after which you allocate the accordant buffer, rewind the file, and read into your buffer.
Alternatively, you can pre-allocate an arbitrarily large buffer, and not worry about the unused amounts. You could be more thrifty if you need to read many different amounts, by pre-allocating memory that you parcel out optimally to read each string, possibly using realloc() if you exhaust the buffer.
fread() does not do a string oriented read, in the sense of, say fscanf(), which will null-terminate a string scanned with the %s format specifier. fread() is data-agnostic, and simply either fills the specified buffer, or not, if end-of-file. If the 'binary' data contains null terminators, perhaps that is what you want to use, but it's worth a re-think, in my opinion.
Your declaration is only appropriate if you intend to use the string pointer for dynamic memory allocation. If you want to allocate storage for your string using the definition, you must define it as an array type.
char string[1000];
Upvotes: 2
Reputation: 40894
As long as you keep track of how much memory you actually use, there should be no problem allocating more memory than you'll use (within reasonable limits – you don't allocate 64 kB for an 8-byte string).
fread
returns the number of elements read (which may be less than the number of items requested), if you're reading a string, you should add a 0
byte after this many bytes in your allocated string:
// we'll read at most 255 bytes
// C strings always need one extra '\0' byte at the end, though
char *string = malloc(256);
// open file "test.txt"
FILE *fp = fopen("test.txt", "r");
// read text from file, and store the number of characters read in len
size_t len = fread(string, sizeof(char), 255, fp);
// note that you can't use strlen(string) here because string doesn't have any data
// so we just tell it to read "as many bytes it can, up to a maximum of 255"
// add '\0' byte to the end because all C strings require this,
// and fread() doesn't add this for us
string[len] = '\0'; // note that string[len] is the (len+1)th character
Upvotes: 0