Click to See Complete Forum and Search --> : STL: how to use a char array as an input stream


spetros
March 6th, 2003, 06:02 PM
My application receives BINARY word-aligned data via character arrays. In other words, the sending application has a struct containing floats, ints, chars, etc. and what the application does is basically memcpy the struct into a char buffer and sends that buffer to my application.

My application recieves (a copy of) the buffer in a message, drops the buffer to a file, and then uses ifstream to open the file as a stream and reads data from it.

My question is can I cut out the "dropping the buffer to a file" part and read data directly from the allocated char buffer as if it was a stream? If so, how do I set up the char buffer as an input stream?

Thank you for your advice.

shridharng
March 6th, 2003, 10:30 PM
Use std::stringstream.

char *inputdata = GetCharBufData();

std::stringstream s;
s << inputdata;

int i;
s >> i;

stober
March 7th, 2003, 10:16 AM
Is this what you want to do?

typedef struct
{
long a;
double b;
float c;
char buf[126];
} DATA;

int main(int argc, char* argv[])
{
char iobuf[sizeof(DATA)];

// get iobuf from the stream
DATA* pData = reinterpret_cast<DATA*>(iobuf);
// now use pData
return 0;
}

PaulWendt
March 7th, 2003, 10:53 AM
Originally posted by shridharng
Use std::stringstream.

char *inputdata = GetCharBufData();

std::stringstream s;
s << inputdata;

int i;
s >> i;

This is absolutely correct. You can save line and use the
constructor of s to initialize it with the char* too :)

spetros
March 21st, 2003, 01:28 PM
First off, thank you for the replies. However, this:

> Use std::stringstream.
>
> char *inputdata = GetCharBufData();
>
> std::stringstream s;
> s << inputdata;
>
> int i;
> s >> i;

isnt exactly working. You see, the character data (inputdata) contains NULLs. The stringstream reads upto the NULL and stops. If I drop the buffer to a file and then read it as an ifstream, everthing works fine.

What I am trying to do is reuse a method that takes in an ifstream and reads binary data from it. Like this:
void myClass::Read(ifstream* inputStream)
{
//inputStream.read(data)
//etc.
}
but this data can also arrive as a char buffer. So I changed the Read signature to expect an istream instead of an ifstream, and provided two constructors to the class like this:
Read is now:
void myClass::Read(istream* inputStream)
//first constructor
myClass(char* inputBuffer)
{
//create a stringstream as above from buffer
//call Read with stringstream
}

//second constructor
myClass(std::string inputFilename)
{
//create an ifstream using the inputFilename
//call Read with ifstream
}

I always have the option of dropping the buffer to a temporary file and using the Read with the ifstream, but that seems wastefull to me.

so what am I missing? Can I create an istream from a char buffer that ignores nulls? :confused:

Philip Nicoletti
March 21st, 2003, 03:15 PM
I think there are a few problems. First, when initializing
the stringstream with a char*, it stops at NULL. Second,
you should read binary. One way around the NULL problem
is to create a std::string from the buffer and use it in
the stringstream (which increases memory requirements).
With the following type of setup, you can use the same
function to read the data, whether using stringstream
or ifstream :


#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <fstream>

using namespace std;

template <class STRM>
STRM & ReadData(STRM & strm)
{
int ii;
float ff;
double dd;
int jj;

strm.read( (char*)(&ii),4);
strm.read( (char*)(&ff),4);
strm.read( (char*)(&dd),8);
strm.read( (char*)(&jj),4);

cout << "ii = " << ii << endl;
cout << "ff = " << ff << endl;
cout << "dd = " << setprecision(10) << dd << endl;
cout << "jj = " << jj << endl;

return strm;
}

int main()
{
char buf[20];

int i = 1;
float f = 3.14159f;
double d = 2.718213452;
int j = 109;

memcpy(&buf[0] ,&i,4);
memcpy(&buf[4] ,&f,4);
memcpy(&buf[8] ,&d,8);
memcpy(&buf[16],&j,4);

ofstream out("test.dat",ios::binary);
out.write(buf,20);
out.close();

// read using stringstream

string strBuf(buf,buf+20);

stringstream ss(strBuf);
ReadData(ss);

// read using file

ifstream in("test.dat",ios::binary);
ReadData(in);
in.close();


return 0;
}