Reputation: 1
I'm writing some serial port code and need to read the contents of a file (in binary) to a variable. Starting from the example for "Binary files" at http://www.cplusplus.com/doc/tutorial/files/ , I try opening a .jpg file:
#include <iostream>
#include <fstream>
using namespace std;
ifstream::pos_type size;
char * memblock;
int main () {
ifstream file ("example.jpg", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
cout << memblock << endl;
delete[] memblock;
}
else cout << "Unable to open file";
return 0;
}
However, only the first 4 characters (32 bits) are printed in the console.
What's particularly odd though is that using ostream::write() with that supposedly faulty variable "memblock" works perfectly:
ofstream fileOut ("writtenFile.jpg",ios::out|ios::binary);
fileOut.write(memblock,size);
fileOut.close();
ie it creates a new .jpg file.
So my question is why the memblock variable seems to only contain the first 4 characters.
Upvotes: 0
Views: 424
Reputation: 154037
Hmmm. A quick glance at the page you cite shows that the author doesn't know much about IO in C++. Avoid it, since much of what it says is wrong.
For the rest: .jpg
is not a text format, and cannot be simply output
to cout
. When you use <<
, of course, the output stops at the first
'\0'
character, but all sorts of binary data may cause wierd effects:
data may be interpreted as an escape sequence repositionning the cursor,
locking the keyboard (actually happened to me once), etc. These
problems will occur even if you use std::cout.write()
(which will not
stop at the '\0'
character). If you want to visualize the data,
your best bet is some sort of binary dump. (I use something like the
following for visualizing large blocks of data:
template <typename InputIterator>
void
process(
InputIterator begin,
InputIterator end,
std::ostream& output = std::cout )
{
IOSave saveAndRestore( output ) ;
output.setf( std::ios::hex, std::ios::basefield ) ;
output.setf( std::ios::uppercase ) ;
output.fill( '0' ) ;
static int const lineLength( 16 ) ;
while ( begin != end ) {
int inLineCount = 0;
unsigned char buffer[ lineLength ] ;
while ( inLineCount != lineLength && begin != end ) {
buffer[inLineCount] = *begin;
++ begin;
++ inLineCount;
}
for ( int i = 0 ; i < lineLength ; ++ i ) {
static char const *const
separTbl [] =
{
" ", " ", " ", " ",
" ", " ", " ", " ",
" ", " ", " ", " ",
" ", " ", " ", " ",
} ;
output << separTbl[ i ] ;
if ( i < inLineCount ) {
output << std::setw( 2 )
<< static_cast< unsigned int >(buffer[ i ] & 0xFF) ) ;
} else {
output << " " ;
}
}
output << " |" ;
for ( int i = 0 ; i != inLineCount ; ++ i ) {
output << (i < lengthRead && isprint( buffer[ i ] )
? static_cast< char >( buffer[ i ] )
: ' ') ;
}
output << '|' << std::endl ;
}
}
(You'll also want to read into an std::vector<char>
, so you don't have
to worry about freeing the memory.)
Upvotes: 0
Reputation: 6647
There is probably a 0 in your binary data. cout
is a text stream so looks at memblock
as a string. If it reaches a null character then it thinks the string has finished.
See this for some help pin outputting binary data: How to make cout behave as in binary mode?
Upvotes: 1