RTC222
RTC222

Reputation: 2323

C function fread() does not read entire file

In C, I am reading the entire contents of the file Data_A into a buffer created with malloc(). The file contains 1000 random integers in the range 5 to 1000.

When I read the file, the newLen variable (see below) shows that the read size is 1001. When I iterate over it as shown below, I get valid numbers (each number correctly corresponds to what's in the file), until it reaches 250 where it returns a negative number. Obviously it read only 251 integers from a file of 1000 integers, but I don't know why. Here's the code:

char FileA [] = "C:/C_Projects/Data_A";
int *buffer1 = NULL;
FILE *pRead;
FILE *fp = fopen(FileA, "rb");
FILE *ptr_test;

fseek(fp, 0L, SEEK_END);
long bufsize = ftell(fp);
buffer1 = malloc(bufsize + 1);
fseek(fp, 0, SEEK_SET);
int nums_to_read = bufsize / 4;
size_t newLen = fread(buffer1, 1, nums_to_read, fp);
buffer1[++newLen] = '\0';

fclose(fp);

// Iterate
int i;
int abc;
int bcd;

for (i = 0; i < bufsize / 4; i++)
{
    abc = buffer1[i];

    if (abc < 0)
    {
        bcd = 0;
    }
    if (i >= 200)
    {
        bcd = 0;
    }
}

As I said, all numbers in the file are positive numbers between 5 and 1000; there are no zeroes or negative numbers. So I don't understand why it's not reading all 1000 integers. The variable bufsize confirms that the buffer is 4000 bytes.

Any ideas will be most appreciated.

Upvotes: 1

Views: 3086

Answers (3)

pm100
pm100

Reputation: 50210

the error is here

int nums_to_read = bufsize / 4;
size_t newLen = fread(buffer1, 1, nums_to_read, fp);

the second param to fread is the size of the elements to read. the third is how many to read. It seems you intent is to read 4 bytes numbers (since you divieded the length by 4). So you should say

int nums_to_read = bufsize / 4;
size_t newLen = fread(buffer1, 4, nums_to_read, fp);

This skip over the whole issue of - are your ints 4 bytes. And is the file really raw 4 bytes ints.

Upvotes: 0

chux
chux

Reputation: 154169

Code has various problems and weaknesses, the biggest was a scant read. @Marcus Müller @Retired Ninja
1 was too small an element size

// fread(buffer1, 1, nums_to_read, fp);
// read nums_to_read elements
// Each elements has the size of `sizeof buffer[0]`
fread(buffer1, sizeof buffer[0], nums_to_read, fp);

Other improvements in code. Handle_Error() is some error handling code to be written.

char FileA [] = "C:/C_Projects/Data_A";
// FILE *pRead;  // not used here
FILE *fp = fopen(FileA, "rb");
if (fp == NULL) Handle_Error();
// FILE *ptr_test;  // not used here

fseek(fp, 0, SEEK_END);
long bufsize = ftell(fp);
if (bufsize == -1) Handle_Error();

int *buffer1 = malloc(bufsize + sizeof *buffer1);
if (buffer1 == NULL) Handle_Error();

// fseek(fp, 0, SEEK_SET);
rewind(fp);  // rewind is sufficient and more clear

// int nums_to_read = bufsize / 4;
size_t nums_to_read = (size_t) bufsize / sizeof *buffer1;

size_t newLen = fread(buffer1, sizeof buffer[0], nums_to_read, fp);
if (newLen != nums_to_read) Handle_Error();

// buffer1[++newLen] = '\0';
buffer1[newLen] = 0;
fclose(fp);

int bcd = 1; // likely should have a default value
// Iterate
// for (int i = 0; i < (size_t) bufsize / 4; i++) {
for (size_t i = 0; i < newLen; i++) {
    int abc = buffer1[i];

    if (abc < 0) {
        bcd = 0;
    }
    if (i >= 200) {
        bcd = 0;
    }
}

Upvotes: 1

RTC222
RTC222

Reputation: 2323

I answered this in the final comment above, but to make this post appear as an answered question, I am posting this here too. Changing the fread line to size_t newLen = fread(buffer1, sizeof(int), nums_to_read, fp); corrected the problem and now it reads the entire file.

Thanks very much to @Retired Ninja and the others who replied to this question.

Upvotes: 0

Related Questions