Solved

Binary File I/O problem

Posted on 1998-12-16
17
241 Views
Last Modified: 2013-11-15
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...
0
Comment
Question by:ris
  • 7
  • 6
  • 2
  • +2
17 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1180318
I see that the ios:binary is commented out.  Why?  that is necessary for what you are doing.
0
 
LVL 1

Author Comment

by:ris
ID: 1180319
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
 
LVL 1

Author Comment

by:ris
ID: 1180320
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
 
LVL 1

Author Comment

by:ris
ID: 1180321
I'm increasing the points because it is really important to me to get this working in the next 2 days
0
 
LVL 22

Expert Comment

by:nietod
ID: 1180322
>>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
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1180323
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
 
LVL 22

Expert Comment

by:nietod
ID: 1180324
<< 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
 

Expert Comment

by:olingk
ID: 1180325
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 22

Expert Comment

by:nietod
ID: 1180326
You can read and write multi-byte quantities with a binary stream with no problem.
0
 
LVL 1

Author Comment

by:ris
ID: 1180327
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
 
LVL 1

Author Comment

by:ris
ID: 1180328
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
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1180329
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
 
LVL 1

Author Comment

by:ris
ID: 1180330
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
 
LVL 22

Accepted Solution

by:
nietod earned 200 total points
ID: 1180331
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
 

Expert Comment

by:olingk
ID: 1180332
Once again:
Did you test it until know?!?
I mean reading 2 Bytes to int ?!?
0
 
LVL 1

Author Comment

by:ris
ID: 1180333
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
 
LVL 22

Expert Comment

by:nietod
ID: 1180334
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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

I previously wrote an article addressing the use of UBCD4WIN and SARDU. All are great, but I have always been an advocate of SARDU. Recently it was suggested that I go back and take a look at Easy2Boot in comparison.
The article will include the best Data Recovery Tools along with their Features, Capabilities, and their Download Links. Hope you’ll enjoy it and will choose the one as required by you.
This video will demonstrate how to find the puppet warp tool from the edit menu and where to put the points to edit.
Viewers will learn how to use the Hootsuite Dashboard.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now