shaiko
shaiko

Reputation: 179

C++ file IO - ASCII value instead of Binary value

I wanted to create a single byte binary file with only one byte in it: 0x01. This is the program I wrote in C++ :

#include <iostream>
#include <fstream>
using namespace std ;

int main ( )
{
    ofstream some_file ("some_file.bin", ios::out | ios::app | ios::binary);
    some_file << 0x01 ;
    some_file.close( );
    return 0;
}

When I inspect the created file using a hex editor - I see the value 0x31 instead of 0x1. Why is that ?

Upvotes: 3

Views: 1140

Answers (3)

walnut
walnut

Reputation: 22152

0x01 is an integer literal. Integer literals are always of integer type with rank at least that of int. Therefore they cannot be of type char (or signed char/unsigned char).

In your case 0x01 will have type int.

char and its signed/unsigned variants are the only integral type for which operator<< on an std::ostream will output a single character represented by the value held in the char.

For other integral types operator<< will output the integer value formatted in decimal representation.

If you want to print the single character from its ASCII code, you need to cast 0x01 to char:

some_file << char{0x01};

or use a character literal:

some_file << '\x01';

or you can use the put method to place a single character, which takes a char parameter and will therefore cause implicit conversion of the int literal to char, which will then be printed as one character represented by the value:

some_file.put(0x01);

or

some_file.put('\x01');

Contrary to <<, put will write the character directly without change. << is affected by formatting options that can be set on the stream, e.g. there could be padding added. If you want to be absolutely sure that only the single character is printed without change, put is probably the correct choice.

Upvotes: 6

Pete Becker
Pete Becker

Reputation: 76235

ios::binary doesn’t really mean “I’m writing a binary file”. It means “don’t do text-mode translations” which primarily means don’t write carriage-return line-feed when the program inserts \n into the stream under Windows.

Stream inserters translate numeric values into their text representation, regardless of the stream’s mode. This is referred to as “formatted output”. To write unformatted values, use std::basic_ostream::write, like this:

int value = 0x01;
some_file.write(&value, sizeof(value));

Upvotes: 1

J. Doe
J. Doe

Reputation: 496

You get 0x31 (49) because You're using operator<<() which is used to write formatted data. Use std::basic_ostream::put() or std::basic_ostream::write() to write data as it is.

Upvotes: 4

Related Questions