Skip to main content
GameDev.net gamedev.net
🔒 Locked

C++ File I/O Binary Vs Text

Started by retroworld Nov 20, 2010 at 10:40 AM 9 replies 3.5k views
Original Post
retroworld
retroworld
I have been trying to figure out what the difference is with binary and text file Input and Output.

I outputted a file in both binary and text mode. then I opened the in notepad and the result is the same. also the file size is also the same.

What are the advantages of using binary over text more?

Also for some files such as 3d max models, when you open them using notepad, you get random symbols. the 3ds max fileformat is written in binary mode.

but the .obj file format is written in text format. so when you open it in notepad, you can see exactly everything.

how come my output in binary mode doesn't have random symbols and why is the filesize the same?

darkelf2k5
darkelf2k5
For binary I/O, use the read/write member functions. <> ops will do text I/O only AFAIK.

123102309:
Text mode: 123102309
Binary mode: edVÌ or something similar

Writing a 32 bit int in binary should take 4 bytes exactly. Doing it in text mode it takes a byte size od at least the amount of digits needed to represent the number.
Every time you implement a singleton, God kills a kitten. Please, think of the kittens!
jpetrie
jpetrie
"text" versus "binary" only has to do with how the data is translated before being written to or read from the file. Mainly this has to do with how newlines will be interpreted and such.
darkelf2k5
darkelf2k5
I does if you write numbers. Dumping text will take the same space.
To use binary I/O you need to create the stream with the binary flag.
std::ofstream fout( "out.txt", ios::out | ios::binary );
Then use fout.write(...).
Every time you implement a singleton, God kills a kitten. Please, think of the kittens!
retroworld
retroworld
thanks allot.

yeah usually I open it like

ofstream f("file.dat", ios::binary);f << "this is a line123";f.close();


I will start doing the write function from now on.

does the write function also work for text files?
darkelf2k5
darkelf2k5
It should. But of course then you need to format it yourself. If you just dumping done text, it's no problem.
Every time you implement a singleton, God kills a kitten. Please, think of the kittens!
KulSeran
KulSeran
Ok. For starters, to recap:

ofstream f("file.data", ios::binary);int i = 125;f << "this is output in text mode" << i << std::endl;f.write( "binary", 7 );f.write( &i, sizeof(i) );f.close();


Now, as to why or why not to use binary formats:
Why not?
-Binary formats aren't human readable. For many things, it is nice to be able to pop open your favorite editor and modify/verify the data.
-Binary formats aren't strictly portable.1

Why use them?
-Binary formats tend to be smaller, as numbers usually take more digits to write out than their binary representation.
-Binary formats are the result of running your data through compression APIs like zlib. Text data, when compressed better uses the available bits in the file to represent the same information.
-Binary formats, because they are smaller, load faster.
-Ignoring compression, binary data tends to require less parsing than text data to get it into your structures.


1 Not all machines have the same memory layout or default data sizes. You should use the built in uint32_t datatypes when dealing with binary files to avoid size problems. Comparing 32bit and 64bit compiles of your code can have different sizeof(int) or sizeof(long), resulting in issues when reading the data from the other compile. Also, there are Endianness differences between processors like the x86 in your PC and the PPC Xenon in the X360. Data written on one can end up being read backwards on the other.


retroworld
retroworld
In write function, the first argumenent is a char *
how come you given it an address to a int?

or is that, you're giving the address to a pointer to point to the data? but the data is an int? what if it was a struct?
Buckeye
Buckeye
Quote:
In write function, the first argumenent is a char *
how come you given it an address to a int?

A small error on Kulseran's part. The write function is really just looking for a memory address from which to retrieve the data to be written. To stop the compiler from complaining:

f.write( (char*)&i, sizeof(i) );

As a matter of preference, I would also change the above to:

f.write( (char*)&i, sizeof(int) );

That last line helps to make you think about how many bytes you're writing to the output. Inevitably, someone will use a pointer to an array with sizeof( pointer_to_array ) rather than sizeof( total_size_of_array ). Without taking care, in some circumstances, that results in writing the size of the pointer and not the size of the array it points to.

EDIT:
Quote:
what if it was a struct?

struct myStruct { ... };myStruct InstanceOfStruct;f.write( (char*)&InstanceOfStruct, sizeof( myStruct ) );

EDIT2:
Be careful casting the pointer if the variable you're writing is a pointer to begin with.
struct myStruct { ... };myStruct *InstanceOfStruct;InstanceOfStruct = new myStruct;f.write( (char*)&InstanceOfStruct, sizeof( myStruct ) ); // WRONG! InstanceOfStruct is already a pointer!f.write( (char*)InstanceOfStruct, sizeof( InstanceOfStruct ) ); // WRONG! sizeof( InstanceOfStruct ) is the size of a pointer, not the size of the structuref.write( (char*)InstanceOfStruct, sizeof( myStruct ) ); // CORRECT
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
KulSeran
KulSeran
Quote:

Origional post by Buckeye
A small error on Kulseran's part

Whoops! forgot the cast. And yes, the issue of sizeof( pointer ) is a good reason to use sizeof(int) instead of sizeof(i)

Quote:

What if it is a struct?

well Buckeye's example is correct:
struct myStruct { ... };myStruct InstanceOfStruct;f.write( (char*)&InstanceOfStruct, sizeof( myStruct ) );

But not future proof. Look up the #pragma pack and Endianness to see why just dumping structures out to a file can be bad. You need to get a good idea of what the compiled code is going to actually put in the files before you go off doing binary file IO. Lots of little things can change between platforms, compilers, and target computers. If you have to compile multiple versions of your code (ie a 32bit and a 64bit exe) then you are likely to run into these things.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.