【问题标题】:Binary read/write to std::stringstream二进制读/写到 std::stringstream
【发布时间】:2013-02-25 15:25:51
【问题描述】:

我有以下代码试图读取/写入无符号整数和 std::wstring 到 std::stringstream。

#include <memory>
#include <iostream>
#include <vector>
#include <sstream>

class SerializationException : public std::runtime_error
{
public:
    SerializationException( const char* msg ) : std::runtime_error( msg ) { }
};

class Serialization
{
public:
    static void Write( std::ostream& stream, const std::wstring& item )
    {
        Write(stream, eStdWString);
        Write(stream, item.length());
        stream.write( reinterpret_cast< const char* >( item.c_str() ), item.length() );
    }

    static std::wstring ReadWString( std::istream& stream )
    {
        const unsigned int type = ReadUInt32(stream);
        if ( type != eStdWString )
        {
            throw SerializationException("Expected eStdWString");
        }
        const unsigned int length = ReadUInt32(stream);
        std::vector< wchar_t > tmpBuf( length );
        stream.read( reinterpret_cast< char* > ( tmpBuf.data() ), length );
        return std::wstring( tmpBuf.begin(), tmpBuf.end() );
    }

    static void Write( std::ostream& stream, const unsigned int& item )
    {
        const unsigned int type = eUInt32;
        stream.write( reinterpret_cast< const char* >( &type ), sizeof(type) );
        stream.write( reinterpret_cast< const char* >( &item ), sizeof(item) );
    }

    static unsigned int ReadUInt32( std::istream& stream )
    {
        const unsigned int type = 0;
        stream.read( reinterpret_cast< char* > ( type ), sizeof(type) );
        if ( type != eUInt32 )
        {
            throw SerializationException("Expected eUInt32");
        }
        const unsigned int tmp = 0;
        stream.read( reinterpret_cast< char* > ( tmp ), sizeof(tmp) );
        return tmp;
    }

private:
    enum eTlvBlockTypes
    {
        eStdWString,
        eUInt32
    };
};

int main(int, char**)
{
    std::wstring myStr = L"HelloWorld!";
    int myInt = 0xdeadbeef;

    try
    {
        std::stringstream ss( std::ios_base::out | std::ios_base::in | std::ios_base::binary );
        Serialization::Write( ss, myStr );
        Serialization::Write( ss, myInt );

        myInt = Serialization::ReadUInt32( ss );
        myStr = Serialization::ReadWString( ss );
    }
    catch (const std::runtime_error& ex)
    {
        std::cout << ex.what() << std::endl;
    }
    return 0;
}

但是在读回流时我得到一个断言失败,因为流为 NULL,有人可以解释这是为什么,以及如何解决它?

编辑:断言失败是 ReadUInt32() 的第二行。

stream.read( reinterpret_cast< char* > ( type ), sizeof(type) );

【问题讨论】:

  • 断言在哪里失败?
  • 我要注意的一点是,你写了一个字符串和一个 int,然后你读回了一个 int 和一个字符串。我认为你有一个倒退。
  • item.length() 为您提供字符串中的元素数,而不是字节数。
  • 你说得对——我也刚刚注意到问题的根本原因,我将一个 int 转换为一个指针,而不是一个 int 的地址,因此它传递一个空指针来读取:(

标签: c++ visual-studio-2010


【解决方案1】:

你需要解决这个问题:

stream.read( reinterpret_cast< char* > ( type ), sizeof(type) );

到这里:

stream.read( reinterpret_cast< char* > ( &type ), sizeof(type) );

再次表明 reinterpret_cast 是危险的

【讨论】:

  • 在这种情况下,您有什么建议避免使用它?
  • 不幸的是,有时这是不可避免的。在这种情况下,我认为他们应该在 std::basic_istream::read 中使用 void * 而不是 char *。至少这将有助于防止这种情况发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多