Reading and Writing Binary File

Reading and writing binary file

If you want to do this the C++ way, do it like this:

#include <fstream>
#include <iterator>
#include <algorithm>

int main()
{
std::ifstream input( "C:\\Final.gif", std::ios::binary );
std::ofstream output( "C:\\myfile.gif", std::ios::binary );

std::copy(
std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>( ),
std::ostreambuf_iterator<char>(output));
}

If you need that data in a buffer to modify it or something, do this:

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
std::ifstream input( "C:\\Final.gif", std::ios::binary );

// copies all data into buffer
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});

}

How do I properly read and write Binary files? (C++)

I see the following problems in your code:

Problem 1

You are using the wrong argument to sizeof in

fread(&p[i], 1, sizeof(p), fin);

and

fwrite(&p[i], 1, sizeof(p), fout);

They need to be sizeof(p[i]), sizeof(p[0]), or sizeof(Pixel). I prefer sizeof(p[0]) since it works regardless of the type of p[0].

Problem 2

You have a typo in

for (uint32_t j = 0; i < bih.width; j++) {

It needs to be

for (uint32_t j = 0; j < bih.width; j++) {
// ^^^ Fix

Problem 3

You are not using the right index to read into p and write from p.

for (uint32_t i = 0; i < bih.height; i++) {
for (uint32_t j = 0; j < bih.width; j++) {

// Using p[i] is not correct. You need to use the right index.
// sizeof(p[0]) is just as good as sizeof(p[index]) here.

uint32_t index = i*bih.width + j;
fread(&p[index], 1, sizeof(p[0]), fin);
}
fseek(fin, padding_bytes, SEEK_CUR);
}

The loop for writing needs to be fixed similarly.

for (uint32_t i = 0; i < bih.height; i++) {
for (uint32_t j = 0; j < bih.width; j++) {
uint32_t index = i*bih.width + j;
fwrite(&p[index], 1, sizeof(p[0]), fout);
}
fseek(fout, padding_bytes, SEEK_CUR);
}

Reading from a text file and writing to a binary file

fscanf - "On success, the function returns the number of items successfully read. This count can match the expected number of readings or be less -even zero- in the case of a matching failure. In the case of an input failure before any data could be successfully read, EOF is returned."

So,you can check to see if it is == EOF in while loop

 while(fscanf(textfile, "%s %s %d %f", firstName, lastName, &id, &gpa) != EOF) {
//Body
}

Alternatively you can also use feof(stdin)

 while(1){ 
fscanf(textfile, "%s %s %d %f", firstName, lastName, &id, &gpa);
if (feof(textfile))
break;
//Body
}

(PS: If you don't want to let the file read <4 number of entries and stop right there, you can do so by replacing EOF with 4 as fscanf returns count as well)

How to write inputs into a binary file and read it in c?

I was wrong at writing into bin file and also reading from it.

First of all I need to thank to @lulle.

  • As he mentioned in comments I changed char* in struct into char arrays.
char initials[80], name[250], email[100], acc_type[25];
  • And I also change file mode. I use ab to writing snippet. And rb in reading snippet.

  • And I changed my writing snippet.

Here I looped over 12 times, this wrote every record 12 time. Sad ah?
This happened because I used just address of struct &new_acc in fwrite. If you use just address of a struct in fwrite`` or fread``` it will write your whole struct. That's what happened to me. I wrote the whole struct 12 time.

for (int i = 0; i <= 12; ++i)  // Looping 12 times  
fwrite(&new_acc, sizeof(new_acc), 1, fp); // writting to file

So instead of looping I changed it into this

fwrite(&new_acc, sizeof(new_acc), 1, fp); \\ This line will write whole struct

But if you want to use members of struct instead of a whole struct, you are free to use a loop. Here is a example. This example is same as above one. But remember to use i or any variable that you used in for loop when writing to file. Instead of i, if you used member name, It will also write 12 times (or as far as you are looping...)

for (int i = 0; i <= 12; ++i)  // Looping 12 times  
fwrite(&new_acc.[i], sizeof(new_acc.[i]), 1, fp); // writting to file
  • And the same thing happened to reading part (I guess...).
    So I changed the code snippet like below
    FILE *fp; 
fp = fopen("employees", "rb");

if (fp == NULL)
puts("Cannot open a file...");

int i = 0;
while(fread(&new_acc, sizeof(new_acc), 1, fp) != 0){ /* use fread one time */
printf("%d\n", new_acc.acc_num);
printf("%s\n", new_acc.name);
printf("%s\n", new_acc.initials);
printf("%s\n", new_acc.birth_day);
printf("%s\n", new_acc.address);
printf("%d\n", new_acc.phone);
printf("%s\n", new_acc.id_num);
printf("%s\n", new_acc.occupation);
printf("%s\n", new_acc.email);
printf("%s\n", new_acc.acc_type);
printf("%d\n", new_acc.balance);

++i;
}

fclose(fp);

Why and how should I write and read from binary files?

You have it all backwards. A computer processor operates with data at the binary level. Everything in a computer is binary. To deal with data in human-readable form, we write functions that jump through hoops to make that binary data look like something that humans understand. So if you store your .BMP data in a file as text, you're actually making the computer do a whole lot more work to convert the .BMP data from its natural binary form into text, and then from its text form back into binary in order to display it.

The truth of the matter is that the more you can handle data in its raw binary form, the faster your code will be able to run. Less conversions means faster code. But there's obviously a tradeoff: If you need to be able to look at data and understand it without pulling out a magic decoder ring, then you might want to store it in a file as text. But in doing so, we have to understand that there is conversion processing that must be done to make that human-readable text meaningful to the processor, which as I said, operates on nothing but pure binary data.


And, just in case you already knew that or sort-of-knew-it, and your question was "why should I open my .bmp file in binary mode and not in text mode", then the reason for that is that opening a file in text mode asks the platform to perform CRLF-to-LF conversions ("\r\n"-to-"\n" conversions), as necessary based on the platform, so that at the internal string-processing level, all you're dealing with is '\n' characters. If your file consists of binary data, you don't want that conversion going on, or else it will corrupt the data from the file as you read it. In this state, most of the data will be fine, and things may work fine most of the time, but occasionally you'll run across a pair of bytes of the hexadecimal form 0x0d,0x0a (decimal 13,10) that will get converted to just 0x0a (10), and you'll be missing a byte in the data you read. Therefore be sure to open binary files in binary mode!


OK, based on your most recent comment (below), here's this:

As you (now?) understand, data in a computer is stored in binary format. Yes, that means it's in 0's and 1's. However, when programming, you don't actually have to fiddle with the 0's and 1's yourself, unless you're doing bitwise logical operations for some reason. A variable of type, let's say int for example, is a collection of individual bits, each of which can be either 0 or 1. It's also a collection of bytes, and assuming that there are 8 bits in a byte, then there are generally 2, 4, or 8 bytes in an int, depending on your platform and compiler options. But you work with that int as an int, not as individual 0's and 1's. If you write that int out to a file in its purest form, the bytes (and thus the bits) get written out in an unconverted raw form. But you could also convert them to ASCII text and write them out that way. If you're displaying an int on the screen, you don't want to see the individual 0's and 1's of course, so you print it in its ASCII form, generally decoded as a decimal number. You could just as easily print that same int in its hexadecimal form, and the result would look different even though it's the same number. For example, in decimal, you might have the decimal value 65. That same value in hexadecimal is 0x41 (or, just 41 if we understand that it's in base 16). That same value is the letter 'A' if we display it in ASCII form (and consider only the low byte of the 2,- 4,- or 8-byte int, i.e. treat it as a char).

For the rest of this discussion, forget that we were talking about an int and now consider that we're discussing a char, or 1 byte (8 bits). Let's say we still have that same value, 65, or 0x41, or 'A', however you want to look at it. If you want to send that value to a file, you can send it in its raw form, or you can convert it to text form. If you send it in its raw form, it will occupy 8 bits (one byte) in the file. But if you want to write it to the file in text form, you'd convert it to ASCII, which depending on the format you want to write it an the actual value (65 in this case), it will occupy either 1, 2, or 3 bytes. Say you want to write it in decimal ASCII with no padding characters. The value 65 will then take 2 bytes: one for the '6' and one for the '5'. If you want to print it in hexadecimal form, it will still take 2 bytes: one for the '4' and one for the '1', unless you prepend it with "0x", in which case it will take 4 bytes, one for '0', one for 'x', one for '4', and another for '1'. Or suppose your char is the value 255 (the maximum value of a char): If we write it to the file in decimal ASCII form, it will take 3 bytes. But if we write that same value in hexadecimal ASCII form, it will still take 2 bytes (or 4, if we're prepending "0x"), because the value 255 in hexadecimal is 0xFF. Compare this to writing that 8-bit byte (char) in its raw binary form: A char takes 1 byte (by definition), so it will consume only 1 byte of the file in binary form regardless of what its value is.



Related Topics



Leave a reply



Submit