Using fread to read in 16 byte blocks - c

I am writing some code that is supposed to read in blocks of 16 bytes at a time from an input file. I am using fread to do this however I run into problems when I get to the last few bytes of the file.
size_t bytesread=1;
while(bytesread > 0){
bytesread = fread(buffer,16,1,inputfile);
buffer[16]='\0';
fprintf("Read in line: "%s"\n,buffer);
}
Say for example my text file is "This is a testfile. Here are some words".
It would print out
Read in line: "This is a testfi"
Read in line: "le. Here are som"
Read in line: "e words
are som"
I can't figure out why it adds on the extra characters when reading in the last line. I understand that I am reading in a block of 16 bytes but how would I deal with the last block where I only want to read in the last 7 bytes?

fread(buffer,16,1,inputfile); attempts to read one block of 16 bytes. If it fails, fread returns zero, indicating that zero complete blocks were read.
You do not want this; you want to know how many characters were read. So use this code, which attempts to read 16 blocks of one byte each:
bytesread = fread(buffer, 1, 16, inputfile);
After this code, bytesread contains the number of bytes read. You can use this to put an end-of-string marker after the last byte read:
buffer[bytesread] = '\0';
Then printf("Read in line: \"%s\"\n", buffer); will print the bytes just read and no more.

Related

Is there a limitation of bytes to be read with fread()

I'm trying to read data from a file into a buffer. The data in file is of 900K bytes. (seek to end of file and ftell()). Allocated the buffer in which the data is to be read of size 900K + 1 (to null terminate). My question is that fread() returns 900K but the I see the strlen(buffer) it shows lesser value and in the buffer at the last I can see something like ".....(truncated)". Why is this behavior? Is there a limit with fread() beyond which we cannot read into buffer and it will truncate it. Also why the return value of fread() says 900K even though actually it has read even less.?
strlen does something along these lines:
int strlen(char *str)
{
int len = 0;
while(*str++) len++;
return len;
}
If your file contains binary data (or if it's a text file with a UTF encoding and unused upper bytes) strlen is going to stop at the first 0x00 byte it encounters and return how many bytes into the file that was encountered. If you read a text file in a single-byte encoding like ANSI there won't be a null terminator and calling strlen will invoke undefined behavior.
If you want to determine how many bytes that fread successfully read out of the file, check its return value.1
If you want to determine the file size before reading a file, do this:
size_t len;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
len will contain the file's size in bytes.
1: Assuming you called fread with parameter 2 set to 1 byte per element and didn't try to read more bytes than are actually in the file.
Your main question has already been answered, though it's worth notice that strlen is not designed to measure the size of an array but a NULL-terminated string. It probably prints a lower value because strlen returns the number of characters that appear before a null-char, so if you have nullchars ('\0') through your data, strlen will stop as soon as it finds one of them.
You should trust fread 's return value.
EDIT: as a note, fread MAY read less bytes than requested, and it can be caused by an error or an end of file. You can check it with ferror and feof, respectively.

fprintf(long) writes 8 bytes and fscanf(long) reads 6 bytes why?

I'm writing a Huffman algorithm and when I write my file header, I store the length of my file because there will be some spare bits and I need to know where to stop.
This happens instead when I write the length of my file: It writes 8 bytes, but when I read, it reads only 6.
long totChar;
long size;
fprintf(outfile, "%ld", totChar);
fscanf(cmpfile, "%ld", &size);
I'm sure that works because if I add for example:
fgetc(cmpfile); \\compressed file
fgetc(cmpfile);
and then I start reading, the decompression is successful.
You're reading and writing characters, not binary.
For example, maybe when you write data, you write the number 57,843,249 (8 digits). But when you read data, you read 875,345 (6 digits).

C Read then Write

After we do:
int readStat = read(fd, buf, sizeof(buf));
Why should the following be:
int status = write(socket_num, buf, readStat);
instead of
int status = write(socket_num, buf, sizeof(buf));
?
So instead of passing in the size of buf, like the man page instructs, why do we pass in the return value of read?!
read returns the number of bytes actually read, keeping in mind you could have a file 500 bytes long, request to read 500 bytes, but only get 200 returned. So you should always loop with read till end of file is returned. This is especially the case with TCP/IP reading, since your pulling from a buffer.
In actuality you probably will always get the amount of bytes you request from a file if there is enough, however this technically is not always true.
But take for example if you had a 32 byte file, and you had a 500 byte buffer. You would only read in 32 bytes, so the other 500 bytes would be garbage. Now when you write your new file, its 500 bytes long, instead of 32.

fread() returns number of read bytes + 1

I use fread to read into a char buffer.
char buffer[50];
int nbytes = fread(buffer, 1, 50, fp);
The file I read from contains exactly the word Hello, i.e. 5 bytes.
In the above example, nbytes equals 6. Why?
Additionally, reading from a zero-byte file (i.e. it's empty) returns 0.
My guess is that whatever wrote to the file you are reading either included a newline (if it's a text file) or a 0 byte after the string. If you are on unix, run the following command:
od -c filename
Which will print the entire contents of the file including non-printables.
You can also run:
wc --bytes filename
Which will print the length of the file in bytes (along with the filename).

Reading Binary file in C

I am having following issue with reading binary file in C.
I have read the first 8 bytes of a binary file. Now I need to start reading from the 9th byte. Following is the code:
fseek(inputFile, 2*sizeof(int), SEEK_SET);
However, when I print the contents of the array where I store the retrieved values, it still shows me the first 8 bytes which is not what I need.
Can anyone please help me out with this?
Assuming:
FILE* file = fopen(FILENAME, "rb");
char buf[8];
You can read the first 8 bytes and then the next 8 bytes:
/* Read first 8 bytes */
fread(buf, 1, 8, file);
/* Read next 8 bytes */
fread(buf, 1, 8, file);
Or skip the first 8 bytes with fseek and read the next 8 bytes (8 .. 15 inclusive, if counting first byte in file as 0):
/* Skip first 8 bytes */
fseek(file, 8, SEEK_SET);
/* Read next 8 bytes */
fread(buf, 1, 8, file);
The key to understand this is that the C library functions keep the current position in the file for you automatically. fread moves it when it performs the reading operation, so the next fread will start right after the previous has finished. fseek just moves it without reading.
P.S.: My code here reads bytes as your question asked. (Size 1 supplied as the second argument to fread)
fseek just moves the position pointer of the file stream; once you've moved the position pointer, you need to call fread to actually read bytes from the file.
However, if you've already read the first eight bytes from the file using fread, the position pointer is left pointing to the ninth byte (assuming no errors happen and the file is at least nine bytes long, of course). When you call fread, it advances the position pointer by the number of bytes that are read. You don't have to call fseek to move it.

Resources