Binary File I/O problem

I am reading a binary file (a windows bmp) and what I get when I do myin>>data and what I see when I do a HEX dump of the file are completely different.  What am I doing wrong?

Here's my code:

{fstream myin(filename,ios::in/* | ios::binary*/);
BitmapFileHeader File;
BitmapInfo Info;
RGBQuad* Colors;
BYTE* BitmapBits;
//read file header
myin>>File.bfType
    >>File.bfsize
    >>File.bfReserved1
    >>File.bfReserved2
    >>File.bfOffBits;

where bfType, bfReserved1, and bfReserved2 are declared as unsigned short (2 bytes for my compiler) and the others are declared as unsigned int (4 bytes for my compiler)

The first 14 bytes of the file (the struct that I am trying to read in above) as seen by a HEX dump program are:

42 4D 08 53 00 00 00 00 00 00 36 00 00 00

but when I read in the data, put a watch on it, and look at the memory dump in hex (which should be the same) I get

8C 3A
60 81 00 00
57 00
00 00
00 00 20 3E

I have never done anything with binary files before this, so I think I am not reading it in correctly.

I am using Borland C++ 5.0

Can anyone help me?  Any suggestions are welcome...
LVL 1
risAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
nietodConnect With a Mentor Commented:
Thanks, but to clarify two points:  

read() and write() only work on char  for fstream's not for basic_fstream, which can work with any type.

Binary mode is not meaningless--but close to it.  It prevents special interpretation of the newline, carriage return, and line feed characters.  It has no effect during a read() or write() operation.
0
 
nietodCommented:
I see that the ios:binary is commented out.  Why?  that is necessary for what you are doing.
0
 
risAuthor Commented:
I commented it out as part of my experimentation to get the code to work.

Uncommenting it out changed my results, but it still doesn't work.  Now the first two bytes are 00 4F.

The rest are different, too, but not in any kind of pattern than I can tell.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
risAuthor Commented:
I'm starting to suspect that my compiler does not handle binary files.

I wrote this code just to simplify my problem a little bit and to play with binary files in general

{
  fstream myio("test.ris",ios::out|ios::binary);
  int a=10;
  int b=20;
  myio<<a<<b;
  myio.close();
  myio.open("test.ris",ios::in|ios::binary);
  myio>>b>>a;
  myio.close();
  cout<<a<<endl<<b<<endl;
}

What happens is that the CHARACTERS 1020 are written to the file (as they would be if it were non-binary) and then when I read them back in, it reads it as an ascii file and reads the number 1020 into b and stops because it reaches eof, so the cout on the last line prints

10
1020

So obviously, either my compiler doesn't implement binary files for some reason (I doubt it) or I have done something wrong, but according to my documentation, I have done everything correctly.

What am I missing?
0
 
risAuthor Commented:
I'm increasing the points because it is really important to me to get this working in the next 2 days
0
 
nietodCommented:
>>I'm starting to suspect that my compiler does not handle binary files
I'm sure that is not the case.

Is that ALL the code you have involving that file or that stream object?  i.e is it possible tha the file is getting written over by something else?
0
 
rwilson032697Commented:
I think the problem is that the behaviour of the << operator is to output the number as a string to the file. The fact the file is binary does not necessarily matter. I think you need to override the << operator (or find the stream class that implements it in the way you want it.

Cheers,

Raymond.
0
 
nietodCommented:
<< outputs in the current mode.

ris, if you could post your entire program or mail it to nietod@theshop.net.  I might be able to see something.
0
 
olingkCommented:
I'm sorry, 'cause there's not much time (not only for you, but for me, know!)
Idea:
I didn't have time to verify it, but I think the problem is reading 2 x 2 Bytes into
a long. Think about this:
You have two Bytes:
Hex. A -> 1011 binary
Hex. B -> 1100 binary

Concated: Hex. AB, but binary concated 10111100 is Hex. D0. (Don't know if I
"computed" right!).
So, try to read Byte by Byte, perhaps by using pure C-Code fread(..) function.
So long ...
0
 
nietodCommented:
You can read and write multi-byte quantities with a binary stream with no problem.
0
 
risAuthor Commented:
I have noticed that if I read in a char (1 byte at a time) it works correctly.  However, that is the case in ascii mode as well as binary, so it supports my theory that my file is not being openned in binary mode for some reason.

My "test-the-binary-mode" program above (the one from Wednesday, December 16 1998 - 07:16PM PST) is the whole program that I wrote just for the purpose of playing with binary files (which, as stated above, didn't work)  There is no way that that file (test.ris) was being touched by anything else at the time.

nietod: I'll mail you my code in a couple minutes.
0
 
risAuthor Commented:
ok, now I know it's not me.  I tried CC under unix on my school account and I still get
10
1020
for the output of my test program.
0
 
RONSLOWCommented:
That output is correct

<< is writing the number as a string of characters "1" "0" "2" "0" so when you read in b it reads in the string "1020" and converts it to an int (note you are reading the variables in opposite order to the way you wrote them and a stil has value 10 because it doesnt get changed (b read in all the data).

Don't use << or >> for binary io ... try 'write' instead



0
 
risAuthor Commented:
Actually nietod already answered my question through an email discussion with me and I promised him the points.

We came to the same conclusion: that the << and >> operators always write in ascii mode.  So the only way is to use the read and write operators, which operate on character strings, which essentially means that binary mode is a meaningless thing.

On the good side though, it is possible to do a nice thing like this:

typedef struct {
int x
int y
char z
short a
} mystruct;

char* temp;
mytemp x;
temp=&x;
myin.read(temp,sizeof(x));

and the whole struct is read in all at once.  The write can be done similarly.

To reiterate, I promised the points to nietod, so please do not answer the question unless you are him.
0
 
olingkCommented:
Once again:
Did you test it until know?!?
I mean reading 2 Bytes to int ?!?
0
 
risAuthor Commented:
Yes, I tested reading to bytes into an int (or 4 in the case of my compiler's implementation of int) and I also tested the structure read that I described earlier and both work, at least with Borland C++ compiler...

CC on Unix complains with an error like "bad assignment char* = mystruct*"
0
 
nietodCommented:
It will work on other compilers as well.  That is how the STL designers intend for programs to do binary I/O.  An unfortunate choice, I think.   They could have made the << and >> operations do binary I/O as well as ASCII.

The error you are getting on CC suggests that you forgot to cast the pointer passed to read() or write() to a char * pointer.  it should have been like

MyFile.read( (char *) &mystruct, sizeof(mystruct) );
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.