views:

386

answers:

7

I am trying to read a bmp file using fstream. However it skips the values between 08 and 0E (hex) for example, for values 42 4d 8a 16 0b 00 00 00 00 00 36

it reads

42 4d 8a 16 00 00 00 00 00 36

skipping 0b like it does not even exist in the document.

What to do?

code:

ifstream in;
in.open("ben.bmp", ios::binary);
unsigned char a='\0';
ofstream f("s.txt");
while(!in.eof())
{
    in>>a;
    f<<a;
}

EDIT: using in.read(a,1); instead of in>>a; solves the reading problem but I need to write unsigned chars and f.write(a,1); does not accept unsigned chars. Anybody got a function to do the writing with unsigned chars?

A: 

Make sure you open it as a binary file like so:

ifstream ifs('input.bin', ios::in | ios::binary);

ofstream ofs('output.bin', ios::out | ios::binary);

it is also a good practice to check for ifs.good() to make sure everything is ok with the file you opened

shoosh
Nope, did not make a difference.
Dunya Degirmenci
+1  A: 

When dealing with binary data, use read() as opposed to the overloaded bitwise operators (<< and >>)

If you need to use streams, it is possible to do something like this:

std::ifstream ifs("bar", std::ios::in | std::ios::binary);
std::ofstream ofs("foo", std::ios::out | std::ios::binary);
ofs << ifs.rdbuf();
Yacoby
+6  A: 

Several issues:

while(!in.eof())
{
    in>>a;
    f<<a;
}

is not the right way to read a file - you need to check if the read worked:

while( in >> a)
{
    f<<a;
}

Secondly, if you want to read a file in binary mode, you need to use the read() and related functions - the >> operator will always perform formatted (non-binary) input, no matter what mode the file is opened in.

Edit: write will need a cast:

unsigned char c = 42;
out.write( (char *) & c, 1 );
anon
+6  A: 

The operator>> and operator<< are designed for textual input and output.

For binary files use read() and write().

shoosh
+4  A: 

That is because the stream is interpreting the bytes as ascii characters. 08 through 0e are white space (horizontal tab, newline, vertical tab, carriage return, etc.), which are being skipped over. Like the other answers said, you need to use the read() method of the stream.

KeithB
+3  A: 
#include <fstream>
#include <iostream>
#include <string>

int main(int argc, char *argv[])
{
  const char *bitmap;
  const char *output = "s.txt";

  if (argc < 2)
    bitmap = "ben.bmp";
  else
    bitmap = argv[1];

  std::ifstream  in(bitmap, std::ios::in  | std::ios::binary);
  std::ofstream out(output, std::ios::out | std::ios::binary);
  char a;

  while (in.read(&a, 1) && out.write(&a, 1))
    ;

  if (!in.eof() && in.fail())
    std::cerr << "Error reading from " << bitmap << std::endl;

  if (!out)
    std::cerr << "Error writing to "   << output << std::endl;

  return 0;
}
Greg Bacon
Yeah, this worked. Now trying to figure out why :) Thanks!
Dunya Degirmenci
Dunya Degirmenci
You're welcome!
Greg Bacon
While this answer is fine, it would probably be easier to read and write if you used iterators and algorithms, outlined by Martin.
GMan
+7  A: 

If you want to read the file one byte at a time this is a good use for the istream buffer iterator.

int main()
{
   ifstream in("ben.bmp", ios::binary);  
   ofstream f("s.txt");  

   //
   // Note: this is NOT istream_iterator
   // The major different is that the istreambuf_iterator does not skip white space.
   //
   std::istreambuf_iterator<char>  loop(in);
   std::istreambuf_iterator<char>  end;

   for(; loop != end; ++loop)
   {
       f << (*loop);  
   }

   // You could now also use it with any of the std algorithms
       // Alternative to Copy input to output
            std::copy(loop,end,std::ostream_iterator<char>(f));

       // Alternative if you want to do some processing on each element
       // The HighGain_FrequencyIvertModulator is a functor that will manipulate each char.
            std::transform( loop,
                            end,
                            std::ostream_iterator<char>(f),
                            HighGain_FrequencyIvertModulator()
                          );
}  
Martin York