RenegadeAndy
RenegadeAndy

Reputation: 5690

C using fread to read an unknown amount of data

I have a text file called test.txt

Inside it will be a single number, it may be any of the following:

1
2391
32131231
3123121412

I.e. it could be any size of number, from 1 digit up to x digits. The file will only have 1 thing in it - this number.

I want a bit of code using fread() which will read that number of bytes from the file and put it into an appropriately sized variable. This is to run on an embedded device; I am concerned about memory usage.

How to solve this problem?

Upvotes: 4

Views: 7302

Answers (4)

Zan Lynx
Zan Lynx

Reputation: 54363

Depending on how clever you need to be with the number conversion... If you do not need to be especially clever and fast, you can read it a character at a time with getc(). So,
- start with a variable initialized to 0.
- Read a character, multiply variable by 10 and add new digit.
- Then repeat until done.
Get a bigger sized variable as needed along the way or start with your largest sized variable and then copy it into the smallest size that fits after you finish.

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215547

If you want to avoid over-reading, fread is not the right function. You probably want fscanf with a conversion specifier along the lines of %100[0123456789]...

Upvotes: 2

Jonathan Leffler
Jonathan Leffler

Reputation: 754910

You can simply use:

char buffer[4096];
size_t nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp);

if (nbytes == 0)
    ...EOF or other error...
else
    ...process nbytes of data...

Or, in other words, provide yourself with a data space big enough for any valid data and then record how much data was actually read into the string. Note that the string will not be null terminated unless either buffer contained all zeroes before the fread() or the file contained a zero byte. You cannot rely on a local variable being zeroed before use.

It is not clear how you want to create the 'appropriately sized variable'. You might end up using dynamic memory allocation (malloc()) to provide the correct amount of space, and then return that allocated pointer from the function. Remember to check for a null return (out of memory) before using it.

Upvotes: 4

Matt Lacey
Matt Lacey

Reputation: 8255

One way to achieve this is to use fseek to move your file stream location to the end of the file:

fseek(file, SEEK_END, SEEK_SET);

and then using ftell to get the position of the cursor in the file — this returns the position in bytes so you can then use this value to allocate a suitably large buffer and then read the file into that buffer.

I have seen warnings saying this may not always be 100% accurate but I've used it in several instances without a problem — I think the issues could be dependant on specific implementations of the functions on certain platforms.

Upvotes: 1

Related Questions