Reputation: 11384
I'm trying to parse MIDI, which needs to be read 8 bits (one byte) at a time. On my system(*), ifs.get()
seems to be grabbing 32 bits at a time.
std::ifstream ifs;
ifs.open(FileName, std::fstream::in | std::ios::binary);
std::cout << "size:: " << sizeof(ifs.get()) <<std::endl; // returns 4
Is it possible to simply specify the number of bytes per read so ifs.get()
gets only one byte (8 bits) at a time?
The reason why I believe ifs.get()
is returning more than 8 bits is because:
uint16_t nReadByte = 0;
nReadByte = ifs.get();
std::cout << std::hex << nReadByte <<std::endl;
Produces results like:
3e,28,0,42,28,0,3b,28
But if I set the variable size to 8 bits I get bizarre characters:
uint8_t nReadByte = 0;
nReadByte = ifs.get();
std::cout << std::hex << nReadByte <<std::endl;
@,,,,.,4,p,s,2,
. (These don't seem to be rendering here correctly, but sometimes they look like the letters ETX
and CAN
in a single glyph.
Upvotes: 1
Views: 864
Reputation: 4207
On my system(*),
ifs.get()
seems to be grabbing 32 bits at a time.
Your example proving this is incorrect. First of all, the ifs.get()
inside sizeof
won't even get evaluated, because expressions in sizeof
don't get evaluated. Second of all, std::ifstream
is an alias for std::basic_ifstream<char>
, and ifs.get()
taking no parameters will indeed return one character of the std::basic_ifstream
's character type. Since this is char
in your case, if CHAR_BIT
(defined in <climits>
) is defined as 8 on your system then it will indeed read 8 bits at a time.
The reason sizeof(ifs.get())
is 4 is because ifs.get()
's return value is std::ifstream::traits_type::int_type
which is int
(the reason the return value is not char
is because it may need to return std::ifstream::traits_type::eof()
as well which may not fit in char
). And on your system, sizeof (int)
is 4.
The reason output looks different for uint16_t
and uint8_t
seems to be that for uint16_t
it's actually printing the bytes as hex whereas for uint8_t
it seems to be printing as characters (uint8_t
is an alias for unsigned char
and ostream
s overload operator<<(unsigned char)
to print characters), which is why some are not showing and the output generally looks different.
Upvotes: 4
Reputation: 238351
How do I set the number of bytes read by ifstream get()?
The second parameter is the number of bytes to read, if you give a buffer as the first targument.
On my system(*), ifs.get() seems to be grabbing 32 bits at a time.
You're mistaken. The nullary overload reads exactly one byte. The return type is int
so that it can represent, besides all possible values of a char
, also EOF (End Of File) which is a special value outside the range of char
that is returned if the stream has reached the end.
uint16_t nReadByte = 0; nReadByte = ifs.get(); std::cout << std::hex << nReadByte <<std::endl;
uint16_t
is an alias of unsigned short
or unsigned int
neither of which are character types. When you insert a non-character integer into a character stream, it will be represented as a number corresponding to its numeric value; in this case modified by the std::hex
manipulator.
But if I set the variable size to 8 bits I get bizarre characters:
uint8_t nReadByte = 0; nReadByte = ifs.get(); std::cout << std::hex << nReadByte <<std::endl;
uint8_t
is an alias of unsigned char
which is a character type. When you insert a character into a character stream, it will not be represented by a number corresponding to its numeric value. Instead, it will be represented by a symbol corresponding to the value in the current character encoding. Some values aren't visible symbols, but rather control characters that affect how a terminal behaves for example.
If you want to stream the numeric value of a character object, then you must convert to another integer type such as unsigned int
.
(These don't seem to be rendering here correctly
When used in contexts where they aren't meaningful, control characters may helpfully be shown with a visible symbol, but not all fonts have such place-holders and websites often remove them when sainiting user input.
Upvotes: 2
Reputation: 697
it seemes ifstream::read is better.
from https://www.cplusplus.com/reference/istream/istream/read/
istream& read (char* s, streamsize n);
Read block of data
Extracts n characters from the stream and stores them in the array pointed to by s.
Upvotes: 1