stella
stella

Reputation: 51

Read txt file by using fread() function

In this code I am trying to read all the data from the file using the fread() function. The problem is that nothing is read in the array. How can fix the error?

#include <stdio.h>

void func(const char *srcFilePath)
{
    FILE *pFile = fopen(srcFilePath, "r");
    float daBuf[30];
   
    if (pFile == NULL)
    {
        perror(srcFilePath);
    } else {
        while (!feof(pFile)) {
            fread(daBuf, sizeof(float), 1, pFile);
        }
    }
    for (int i = 0; i < 5; i++) {
        printf(" daBuf  = %f \n", daBuf[i]);
    }
}

void main() {
    const char inputfile[] = "/home/debian/progdir/input";
    func(inputfile);
}

The input file has values like this:

1.654107,
1.621582,
1.589211,
1.557358,
1.525398,
1.493311,
1.483532,
1.483766,
1.654107,

Upvotes: 2

Views: 294

Answers (2)

tshiono
tshiono

Reputation: 22062

You may be confusing binary representation and ascii representation of number. Here is a small code to generate a binary file using the first 5 data in your input file.

#include <stdio.h>

int main()
{
    float x[5] = {1.654107, 1.621582, 1.589211, 1.557358, 1.525398};
    char outfile[] = "output.bin";
    FILE *fp;

    if (NULL == (fp = (fopen(outfile, "wb")))) {
        perror(outfile);
        exit(1);
    }
    fwrite(x, sizeof(float), 5, fp);
    fclose(fp);

    return 0;
}

If you compile and execute it, a file output.bin will be generated. As you seem to be working on debian, try xxd command to dump the binary file:

$ xxd output.bin
0000000: c7b9 d33f 0090 cf3f 446b cb3f 8257 c73f  ...?...?Dk.?.W.?
0000010: 3e40 c33f                                >@.?

The first 4-byte data c7b9d33f corresponds to the first number 1.654107. (Note the byte order depends on the endianness of the processor architecture.)

In general we don't care what c7b9d33f means because binary data is not human readable. If you are interested in the format, search google for IEEE754. The important thing is fread() and fwrite() are designed to read/write binary data.

Your posted program can be used to read output.bin with some corrections:

#include <stdio.h>

void func(const char *srcFilePath)
{
    int i;
    float daBuf[30];
    FILE *pFile = fopen(srcFilePath, "rb");

    if (pFile == NULL) {
        perror(srcFilePath);
        exit(1);
    }
    fread(daBuf, sizeof(float), 5, pFile);      // read 5 float data in an array
    for (i = 0; i < 5; i++) {
        printf(" daBuf  = %f \n", daBuf[i]);    // print them
    }
}

int main()
{
    const char inputfile[] = "output.bin";
    func(inputfile);
    return 0;
}

Output:

 daBuf  = 1.654107
 daBuf  = 1.621582
 daBuf  = 1.589211
 daBuf  = 1.557358
 daBuf  = 1.525398

You still have a mistake in the usage of fread(). You are passing the fixed address daBuf to fread() in the loop as fread(daBuf, sizeof(float), 1, pFile). It just modifies the first element daBuf[0] repeatedly without assigning other elements. You can read multiple elements of data at once by passing the length as the 3rd argument to fread().

As you may have roughly grasped the binary data, let's go back to ascii data. Try to dump your input (w/o commas) with xxd:

$ xxd input
0000000: 312e 3635 3431 3037 0a31 2e36 3231 3538  1.654107.1.62158
0000010: 320a 312e 3538 3932 3131 0a31 2e35 3537  2.1.589211.1.557
0000020: 3335 380a 312e 3532 3533 3938 0a31 2e34  358.1.525398.1.4
0000030: 3933 3331 310a 312e 3438 3335 3332 0a31  93311.1.483532.1
0000040: 2e34 3833 3736 360a 312e 3635 3431 3037  .483766.1.654107
0000050: 0a                                       .

If you read the file input by using fread(), the first element daBuf[0], for instance, will be assigned to 4-byte data 312e3635, which will be meaningless as a binary representation.

I hope you will have understood why you cannot use fread() to read ascii files.

Upvotes: 1

Oka
Oka

Reputation: 26375

Your file contains formatted text, so you can use fscanf.

Ensure that you are reading data into a new position in the array every iteration, and that you do not go beyond the bounds of the array.

Use the return value of fscanf to control your loop.

Notice the format string for fscanf is "%f,".

#include <stdio.h>

#define BUFMAX 32

void func(const char *srcFilePath)
{
    FILE *pFile = fopen(srcFilePath, "r");

    if (!pFile) {
        perror(srcFilePath);
        return;
    }

    float daBuf[BUFMAX];
    size_t n = 0;

    while (n < BUFMAX && 1 == fscanf(pFile, "%f,", &daBuf[n]))
        n++;

    if (ferror(pFile))
        perror(srcFilePath);

    fclose(pFile);

    for (size_t i = 0; i < n; i++)
        printf("daBuf[%zu] = %f\n", i, daBuf[i]);
}

int main(void)
{
    const char inputfile[] = "/home/debian/progdir/input";

    func(inputfile);
}
daBuf[0] = 1.654107
daBuf[1] = 1.621582
daBuf[2] = 1.589211
daBuf[3] = 1.557358
daBuf[4] = 1.525398
daBuf[5] = 1.493311
daBuf[6] = 1.483532
daBuf[7] = 1.483766
daBuf[8] = 1.654107

fread is generally intended for binary data, in which case you would open the file with the additional "b" mode.

Here is an example, if your file contained binary data:

#include <stdio.h>

#define BUFMAX 32

void func(const char *srcFilePath)
{
    FILE *pFile = fopen(srcFilePath, "rb");

    if (!pFile) {
        perror(srcFilePath);
        return;
    }

    float daBuf[BUFMAX];
    size_t n = fread(daBuf, sizeof *daBuf, BUFMAX, pFile);

    if (ferror(pFile))
        perror(srcFilePath);

    fclose(pFile);

    for (size_t i = 0; i < n; i++)
        printf("daBuf[%zu] = %f\n", i, daBuf[i]);
}

int main(void)
{
    const char inputfile[] = "/home/debian/progdir/input";

    func(inputfile);
}

Upvotes: 1

Related Questions