使用Endian正确地序列化/反序列化基元

时间:2016-12-22 15:58:58

标签: c++ serialization

对于一个项目,我试图序列化一些原语并通过线路将它们发送到本地托管的Java服务器。 Java部分现在并不那么重要,但重要的是Java将其数据解释为Big Endian,而我的C ++程序是Little Endian。

对于一个小例子,我有一个双:

_fields.degLatitude = 50.0;

然后我想序列化那些数据,还要交换字节顺序(以符合Little-> Big Endian):

char buffer[sizeof(struct Fields)];
char* p = buffer;

writeReversedData<double>(&p, _fields.degLatitude);

writeReversedData的实现在这里:

template <typename T> void JsbSimWrapper::writeReversedData(char** bb, T& data)
{
    const char* charBuffer = std::to_string(data).c_str();

    for (int i = 0; i < sizeof(T); i++)
    {
        (*bb)[i] = charBuffer[sizeof(T) - i - 1];
    }

    *bb += sizeof(T);
}

然后就像我身边的测试一样,我想反序列化这些数据,然后将它交换回Little Endian:

std::cout << getReversedData<double>(&p) << std::endl;

这是getReversedData的实现:

template <typename T> T JsbSimWrapper::getReversedData(char** p)
{
    union temp 
    {
        char bytes[sizeof(T)];
        T tt;
    };

    temp t;

    for (int i = 0; i < sizeof(T); i++)
    {
        t.bytes[i] = (*p)[(sizeof(T) - 1) - i];
    }

    *p += sizeof(T);

    return t.tt;
}

不幸的是,cout只返回了接近50.0的巨大数字。我还测试了Java端收到的数据,它与C ++中的cout匹配,所以它必须与我的写调用有关。

我确信我的getReversedData可以正常工作,因为我在Java端测试它时发送了序列化数据,而C ++方面对它进行了解释。

1 个答案:

答案 0 :(得分:1)

此代码存储指向临时的指针。一旦声明完成,它就会悬空。

const char* charBuffer = std::to_string(data).c_str();

另外,在for循环中

for (int i = 0; i < sizeof(T); i++)
{
    (*bb)[i] = charBuffer[sizeof(T) - i - 1];
}

没有规则字符串表示为sizeof(T)。例如,一个4字节的int可能会转换为10位数。

最好将转换后的结果存储在std::string中,然后使用该字符串的length()