Link to home
Start Free TrialLog in
Avatar of chrishughes
chrishughes

asked on

Opening a binary file in MS Visual C++

I have a binary file with an arbitary number of unsigned Chars, representing a 3d dataset. I am looking for an example of code which will open the file and load the data into a 3d array,

Many Thanks..
Avatar of drichards
drichards

That is not enough information to go on.  What is the format of the file?  Specifically, how is the 3d array laid out?

To open a file in binary mode, you can do:

    #include <fstream>
    ...
        std::ifstream inFile;
        infile.open(filename, std::ios_base::binary);

What you do after that depends on what exactly is in the file.  At that point you use avaliable input methods to fetch the data from the file in the apperopriate manner.
Avatar of chrishughes

ASKER

Hi!

Well I know the 3d data set is x * y * z, and all of the values are unsigned chars in a sequential order..

So what is the ordering of the unsigned char values and how do you know the dimensions x, y, and z?  If you know the dimensions, you can create an appropriate array of unsigned char and do loops:

for ( int z = 0; z < ZDim; z++ )
{
  for ( x = 0; x < XDim; x++ )
  {
    for ( int y = 0; y < YDim; y++ )
    {
        inFile >> arr3d[z][x][y];
    }
  }
}

If you know two of the three dimensions - suppose the file is a set of 'XDim-by-YDim' layers but you don't know how many layers there are - you can change the outer loop to be "while ( !infile.eof() )" which will just keep reading layers until the file is empty.

As you see, you need to have some idea what's in the file and how the data is arranged.
Hi Thanks for your help! I obviously realise that I need to know the order etc of the data - I was more looking for an example of how the actul file handling is done in C++ as I have never tried this before!

:-)
ASKER CERTIFIED SOLUTION
Avatar of drichards
drichards

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If the file is a list of points (i.e. a list of x,y,z coordinates), your 3D array might not be the way to go. You might be better off with a user-defined structure - e.g. struct Coord {unsigned char x,y,z;};. Then use a container for the structure. Then fill the container with the points read from the file.

e.g.
--------8<--------
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm>

struct Coord {unsigned char x,y,z;};
typedef std::vector<Coord> CoordList;
CoordList coordList;

// To display a Coord object
std::ostream& operator<<(std::ostream& os,const Coord& coord)
{
      return os << '(' << static_cast<int>(coord.x) << ',' << static_cast<int>(coord.y) << ',' << static_cast<int>(coord.z) << ')';
}

int main()
{
      std::ifstream fin("x.dat",std::ios::binary);
      Coord coord;
      while (fin.read(reinterpret_cast<char*>(&coord),sizeof(coord)))
            coordList.push_back(coord);
      std::cout << "Coords are: ";
      copy(coordList.begin(),coordList.end(),std::ostream_iterator<Coord>(std::cout,", "));
      std::cout << '\n';
}
--------8<--------
AHHH!!!

Ok so I have made a big mistake in my question... Basically the binary file, contains a list of 32 bit ints. I simply need an example of how to open the file, read each int at a time and output its value to the console.

Many thanks - I have increased the points due to my mistake..
You need to find out if your ints are little-endian or big-endian.
Conventionally ints sent over the network are sent in network byte order, which means big endian. If you are on an Intel platform, you need to convert these to little-endian, which means using the ntohl macro, which you can generally get by including <arpa/inet.h> or <netinet/in.h> (it isn't part of the standard, alas - look at your man page).

If the ints have been generated by the local machine and they've been written directly to file without conversion, you can read them directly into an unsigned long, which ought to provide you with 32 bits (though this isn't guaranteed in the standard) and you can skip the ntohl conversion.

Here's some demonstration code with the conversion macro, which assumes that your ints are in network byte order:
--------8<--------
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif

typedef unsigned long Value;
typedef std::vector<Value> ValueList;
ValueList valueList;

int main()
{
     std::ifstream fin("x.dat",std::ios::binary);
     Value value;
     while (fin.read(reinterpret_cast<char*>(&value),sizeof(value)))
          valueList.push_back(ntohl(value)); // Using ntohl macro
     std::cout << "Values are: ";
     copy(valueList.begin(),valueList.end(),std::ostream_iterator<Value>(std::cout,", "));
     std::cout << '\n';
}
--------8<--------
Hi!

When I try to execute the above code I get the following error:

C:\work\opengl\vertex_volume\example.cpp(44) : error C2079: 'fin' uses undefined class 'basic_ifstream<char,struct std::char_traits<char> >'
C:\work\opengl\vertex_volume\example.cpp(44) : error C2078: too many initializers
C:\work\opengl\vertex_volume\example.cpp(46) : error C2228: left of '.read' must have class/struct/union type
C:\work\opengl\vertex_volume\example.cpp(46) : fatal error C1903: unable to recover from previous error(s); stopping compilation
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial