Sign in to follow this  

c++ datastream

This topic is 4350 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey I looking for something like c++ streams for reding int, long, etc into a buffer and then getting the size of it and the whole buffer. Something like this would be the usage:
void main()
{
    ostream stream();
    stream << "hey" << 1 << 1L;

    int size = stream.size();
    char* buffer = stream.getBytes();
}


My c++ stream knowledge is not so good, are there something in there that will help me with this or do I have to write my own stream, overriding streambuf etc. thanks Lizard

Share this post


Link to post
Share on other sites
#include <sstream>
#include <string>

int main() // void main is not legal standard C++
{
std::ostringstream stream;
stream << "hey" << 1 << 1L;

std::size_t size = stream.str().size();
std::string string = stream.str();

// buffer is only valid while string is valid and unchanged
char const * buffer = string.c_str();
}

Enigma

Share this post


Link to post
Share on other sites
Yes I have tried stringstreams but I think that is not really what I'm looking for, but do correct me if I'm wrong. The thing is that I'm not looking to get a string as output, I'm looking to get a byte array to send over a network, i.e using this for serilazing.
So in the exaple I want the byte array returned to contain first tre bytes for the letters "h", "e", and "y" and then four bytes for the integer 1, and then four (both long and int is 4 bytes in c++, isn't it) bytes for the long value 1L.

I have tried things like the one Enigma describes above and things like:

#include <iostream>
#include <sstream>

using namespace std;

void main()
{
stringstream stream;
int i = 1;
stream << i;
stream.seekg(0, ios::end);
int length = stream.tellg(); // length will be 1, expected 4
char* buffer = new char[length]; // char array will be the ascii code for '1' expected was the int value 1
stream.read(buffer, length);

return;
}






but thanks for fast answers


Lizard

Share this post


Link to post
Share on other sites
The insertion and extraction operators on C++ stream types are for formatted I/O. You use the read() or write() member functions to perform binary I/O. If you want to use operator<< or operator>> for binary I/O then you'll need to write wrappers or your own stream class.

Share this post


Link to post
Share on other sites
On the other hand, if you did want formatted I/O, you should be aware that you can easily get a const char* alias to the std::string's storage (note constness; you will need to make some kind of copy if you have to change the data) by its .c_str() member function.

Share this post


Link to post
Share on other sites
Quote:
Original post by LizardCPP...both long and int is 4 bytes in c++, isn't it...
Lizard


Oh please note: the size of int and long is not always the same and has nothing to do with the language you are programming in.

A long will always be 4 bytes, but the size of an int depends on the Operating System (OS) you are working on. If you use Windows XP 32-bit edition for an example, then yes, int will be 4 bytes, but on the 64-bit edition it will be 8 bytes.

Regards,

Xeile

Share this post


Link to post
Share on other sites
Quote:
Original post by Xeile
A long will always be 4 bytes, but the size of an int depends on the Operating System (OS) you are working on.

Nope. The size of long and int are dependent on the compiler, not the operating system. Also, a long must always be the same size or larger than an int.

Quote:

If you use Windows XP 32-bit edition for an example, then yes, int will be 4 bytes, but on the 64-bit edition it will be 8 bytes.

For most compilers targeting 64 bit x86 architectures ints are still 4 bytes.

Share this post


Link to post
Share on other sites
Microsoft has already posted that int will stay a 4-byte variable in 64-bit and you will need to use the long long type or use the _int64 types if you want an 8-byte. Now this is just how Microsoft is handling it in Visual Studio.

Share this post


Link to post
Share on other sites
Quote:
Original post by Xeile
Quote:
Original post by LizardCPP...both long and int is 4 bytes in c++, isn't it...
Lizard


Oh please note: the size of int and long is not always the same and has nothing to do with the language you are programming in.


What are you talking about? It has plenty to do with the language you are programming in.

In C++, a long is at least as big as an int, but the size of neither is exactly guaranteed.

In Java, a long is signed, 8 bytes. an int is signed, 4 bytes. Full stop.

In Python, an int is an object that wraps a number that has a 4-byte range (roughly equivalent to java.lang.Integer). A long is an object that represents an arbitrary integral number (roughly equivalent to BigInteger in whatever package it's in).

Quote:
A long will always be 4 bytes, but the size of an int depends on the Operating System (OS) you are working on. If you use Windows XP 32-bit edition for an example, then yes, int will be 4 bytes, but on the 64-bit edition it will be 8 bytes.


That's even worse. On a 64-bit platform, int may be 8 bytes. Or 4. Or 23. Similarly long. Similarly on a 32-bit platform, for either. The idea of an int being the "native" integer size is really only a suggestion.

But it is *not* OK on that 64-bit system for long to be 4 bytes while int is 8.

And anyway, platform != OS.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
The insertion and extraction operators on C++ stream types are for formatted I/O. You use the read() or write() member functions to perform binary I/O. If you want to use operator<< or operator>> for binary I/O then you'll need to write wrappers or your own stream class.


Ok this is kindof a *bump*.

I tried to write my own stream class with the help of Boost.Iostreams. It turned out this way:


#ifndef SOCKET_STREAM_H_INCLUDED
#define SOCKET_STREAM_H_INCLUDED

#include <iosfwd>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/positioning.hpp>

#include "ISocket.h"

namespace io = boost::iostreams;

namespace communication
{
class SocketStream
{
public:
typedef char char_type;
typedef io::seekable_device_tag category;

SocketStream(ISocket* socket)
{
this->socket = socket;
}

void connect()
{
if (!socket->isConnected())
{
socket->connect();
}
}

void disconnect()
{
if (socket->isConnected())
{
socket->disconnect();
}
}

std::streamsize read(char* s, std::streamsize n)
{
return socket->recieve(s, n);
}

std::streamsize write(const char* s, std::streamsize n)
{
socket->send(s, n);
return n;
}

io::stream_offset seek(io::stream_offset off, std::ios_base::seekdir way)
{
// Not implemented
return 0;
}

private:
ISocket* socket;
};

}



#endif






The test program:

#include <iostream>
#include "../DiscoridaClient/SocketStream.h"
#include "../DiscoridaClient/SocketFactory.h"
#include <boost/iostreams/stream_buffer.hpp>


namespace io = boost::iostreams;

using namespace std;
using namespace discordia;
using namespace communication;

void main()
{
ISocket* socket = SocketFactory::createSocket("localhost", 4444);
socket->connect();

while(!socket->isConnected()) {}

io::stream_buffer<SocketStream> streamBuffer(socket);
ostream stream(&streamBuffer, ios::binary);

int i = 1;
stream << i << "hey";
stream.flush();

while(socket->isConnected()) {}

return;
}







But still the input i get to SocketStream::read() is a char* with the String "1hey" and the size is 4 bytes. I was expecting 7 bytes, first 4 bytes for the int 1 and then 3 characters h,e,y.

Can't I use Boost.Iostreams for this? If not, can I use c++ stream to do this?

Lizard

Edit: This would be used together with Boost.Serialization to easy serialize data over a network.

[Edited by - LizardCPP on January 15, 2006 10:09:41 AM]

Share this post


Link to post
Share on other sites
You're still using the formatted insertion operators on a C++ stream, which will send the formatted output over your socket. What you can do is create wrappers such as:

struct BinaryInt {
BinaryInt(int i) : i_(i) {}
int i_;
}

std::ostream & operator<<(std::ostream & lhs, BinaryInt rhs) {
lhs.write(reinterpret_cast<const char *>(&rhs.i_), sizeof(int));
return lhs;
}

stream << BinaryInt(i) << "hey";

Alternately you can create your own stream type.

Share this post


Link to post
Share on other sites

This topic is 4350 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this