1

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.

2
  • What are you trying to achieve with this string after reading ? Commented Apr 19, 2014 at 23:27
  • Kinda complicated. The assignment was to emulate the behaviour of a simply linked list using files, where each file emulate the behaviour of a node. The file itself contains a data (could be int, char, etc.) and the name of the next file with data. If the name of the next file is "0.bin", it means it we reached the last file on the list. So, as you can guess, the strings indicate the names of the next files with data. Hopefully I explained myself well. Commented Apr 19, 2014 at 23:32

3 Answers 3

2

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];
Sign up to request clarification or add additional context in comments.

Comments

0

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

4 Comments

Note that this assumes the string is the only thing left in the file. If there's more data after the string, this approach might not be sufficient.
I know I can allocate more memory that what I am actually going to use, but I am trying to avoid doing that. I just want to reserve the exact amount of memory that I want to use.
Short answer: you can't. Long(er) answer: You still can't really, but you can start off small, do multiple reads and reallocate using realloc if you need more (or less) space.
Well, that second option sounds awfully complicated, and I don't even know how to use realloc. Guess I'll just have to do what you are telling me. Thanks for the answer, it is really helpful.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.