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.
Related
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.
If I have a text file with the following content opened as binary
1234567890
a call like this:
fseek(fp, 5L, SEEK_SET);
give me 6 when I call (char)fgetc(fp) because I offset 5 byte from byte 0 (not start from 1 but from 2)
but If I do:
fseek(fp, -3L, SEEK_END);
give me 8 and not 7 when I call (char)fgetc(fp).
Why? It seems as with SEEK_END the offset doesn't start from the previous byte after the last.
SEEK_END searches from the one-past last byte of the file:
1234567890 <--- bytes from the file
0123456789A <--- SEEK_SET-relative position
A9876543210 <--- SEEK_END-relative position (absolute value)
^
This is the (0, SEEK_END) byte
With this in mind, the very last byte of the file is the one found at (-1, SEEK_END) and thus the (-3, SEEK_END) byte is the 8.
Note that this is consistent with how C usually handles this kind of thing. For example a pointer to the end of a memory block will usually point to one-past the last byte of that block.
This also has the nice feature that you can get the size of the file with a call to fseek(SEEK_END) plus ftell(). No need to add or substract 1!
The man page from fseek() is a bit ambiguous about this issue, but compare with the man lseek that contains the same issue:
If whence is SEEK_END, the file offset shall be set to the size of the file plus offset.
In your example the size of the file is 10, and the offset is -3, so the final position is 10-3 = 7. And in offset 7 there is an 8.
fseek allows appending texts to a current file. Therefore the filepointer is set after (!) the last character in the file, because that is the place where new characters are to be appended.
From the start:
01234 <---position
ABCDEFGHIJK <---file content
From the end:
43210 <---position
ABCDEFGHIJK <---file content
So when you are fetching from the start, the 0th character is the A
And the 3rd is D.
But when you are fetching from the end, the 0th characters is EndOfFile
And the -3rd is I.
I think is because of the last character of file is '\n' or '\0' or something like that.
I want to read a video file and save as binary and write as a video file again.
I tested with 180MB video. I used fread function and It occur segmentation fault because array size is small for video.
those are my questions:
I use 160*1024 bytes char array. What is the maximum size of char array? How I can solve this problem?
this program need to work as:
read 128 bytes of video -> Encrypt -> write 128 byte
read next 128 bytes -> Encrypt -> write to the next.
I can't upload my code because of security rule of company. Any tip would be appreciated.
first use fseek() with SEEK_END, then use ftell() to determine the file size, after that allocate the needed memory with malloc() and write the data to that memory.
If I understand you correctly you don't need to allocate so much memory, but only 128 Bytes.
char buf[128];
while(/* condition */)
{
ret = fread(buf, sizeof buf, 1, fp_in);
encrypt(buf);
ret = fwrite(buf, sizeof buf, 1, fp_out);
}
I was 100% sure that the bytes of a wav file are chunkSize + 8,What I've been trying to do
is:
fseek(file_pointer, chunkSize+8-4, SEEK_SET)
and then use
fread(rev, 4, 1, file_pointer)
to put the last 4 bytes to the array rev unsigned char rev[4]. But the bytes it puts in rev are for sure not the 4 last bytes. I've been working on the project for so many hours and I still can't find why this isn't working. If someone can tell me the correct answer I will build a statue of him right now.
If you want to access the last 4 bytes of a file, you can use SEEK_END, like so:
fseek(file_pointer, -4, SEEK_END);
The fread should then return the last four bytes.
I am trying to read a binary file in C 1 byte at a time and after searching the internet for hours I still can not get it to retrieve anything but garbage and/or a seg fault. Basically the binary file is in the format of a list that is 256 items long and each item is 1 byte (an unsigned int between 0 and 255). I am trying to use fseek and fread to jump to the "index" within the binary file and retrieve that value. The code that I have currently:
unsigned int buffer;
int index = 3; // any index value
size_t indexOffset = 256 * index;
fseek(file, indexOffset, SEEK_SET);
fread(&buffer, 256, 1, file);
printf("%d\n", buffer);
Right now this code is giving me random garbage numbers and seg faulting. Any tips as to how I can get this to work right?
Your confusing bytes with int. The common term for a byte is an unsigned char. Most bytes are 8-bits wide. If the data you are reading is 8 bits, you will need to read in 8 bits:
#define BUFFER_SIZE 256
unsigned char buffer[BUFFER_SIZE];
/* Read in 256 8-bit numbers into the buffer */
size_t bytes_read = 0;
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr);
// Note: sizeof(unsigned char) is for emphasis
The reason for reading all the data into memory is to keep the I/O flowing. There is an overhead associated with each input request, regardless of the quantity requested. Reading one byte at a time, or seeking to one position at a time is the worst case.
Here is an example of the overhead required for reading 1 byte:
Tell OS to read from the file.
OS searches to find the file location.
OS tells disk drive to power up.
OS waits for disk drive to get up to speed.
OS tells disk drive to position to the correct track and sector.
-->OS tells disk to read one byte and put into drive buffer.
OS fetches data from drive buffer.
Disk spins down to a stop.
OS returns 1 byte to your program.
In your program design, the above steps will be repeated 256 times. With everybody's suggestion, the line marked with "-->" will read 256 bytes. Thus the overhead is executed only once instead of 256 times to get the same quantity of data.
In your code you are trying to read 256 bytes to the address of one int. If you want to read one byte at a time, call fread(&buffer, 1, 1, file); (See fread).
But a simpler solution will be to declare an array of bytes, read it all together and process it after that.
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);
It is time to read mans I believe.
Couple of problems with the code as it stands.
The prototype for fread is:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
You've set the size to 256 (bytes) and the count to 1. That's fine, that means "read one lump of 256 bytes, shove it into the buffer".
However, your buffer is on the order of 2-8 bytes long (or, at least, vastly smaller than 256 bytes), so you have a buffer overrun. You probably want to use fred(&buffer, 1, 1, file).
Furthermore, you're writing byte data to an int pointer. This will work on one endian-ness (small-endian, in fact), so you'll be fine on Intel architecture and from that learn bad habits tha WILL come back and bite you, one of these days.
Try real hard to only write byte data into byte-organised storage, rather than into ints or floats.
You are trying to read 256 bytes into a 4-byte integer variable called "buffer". You are overwriting the next 252 bytes of other data.
It seems like buffer should either be unsigned char buffer[256]; or you should be doing fread(&buffer, 1, 1, f) and in that case buffer should be unsigned char buffer;.
Alternatively, if you just want a single character, you could just leave buffer as int (unsigned is not needed because C99 guarantees a reasonable minimum range for plain int) and simply say:
buffer = fgetc(f);