序列化和反序列化實現

1. 什麼是序列化?

  程序員在編寫應用程序的時候每每須要將程序的某些數據存儲在內存中,而後將其寫入文件或是將其傳輸到網絡中的另外一臺計算機上以實現通信。這個將程序數據轉換成能被存儲並傳輸的格式的過程被稱爲序列化(serialization),而它的逆過程被稱爲反序列化(deserialization)。ios

  簡單來講,序列化就是將對象實例的狀態轉換爲可保持或傳輸的格式的過程。與序列化相對的是反序列化,它根據流重構對象。這兩個過程結合起來,能夠輕鬆地存儲和傳輸數據。程序員

  序列化:將對象變成字節流的形式傳出去。
  反序列化:從字節流恢復成原來的對象。編程

2. 序列化實現

  能夠經過將對象轉換成json、xml和二進制流的方式實現序列化,鑑於json和xml在不一樣編程語言中其組包、解包的API接口實現方法的不一樣,我決定採用通用的二進制流的方式實現序列化。json

2.1 類圖設計

  

3. 各個組件代碼實現

3.1 元組實現

  該元組能夠接納咱們自定義的任意類型網絡

  數據類型定義:編程語言

enum class Type {
        Invalid,
        Boolean,
        Character,
        Int8,
        Int16,
        Int32,
        Int64,
        Float,
        Double,
        String
    };

  聯合體InnerValue定義:聯合體的優勢在於全部的值共享一篇存儲空間,所以不會引發額外的空間存儲消耗ide

union InnerValue {
        bool booleanValue;
        char characterValue;
        int8_t int8Value;
        int16_t int16Value;
        int32_t int32Value;
        int64_t int64Value;
        float floatValue;
        double doubleValue;
    };

  Values類實現:函數

#include <vector>
class Values : public std::vector<Value>
{
public:
    Values() = default;
    Values(std::initializer_list<Value> list) : std::vector<Value>(list)
    {
    }

    Value& operator[](size_t index) {
        return std::vector<Value>::operator[](index);
    }

    const Value& operator[](size_t index) const {
        return std::vector<Value>::operator[](index);
    }
};

  異常類TypeMismatchException實現:測試

#ifdef WIN32
#define NOEXCEPT
#else
#define NOEXCEPT noexcept
#endif

class TypeMismatchException : public std::exception
{
public:
    TypeMismatchException(const std::string& message) :
        _message(message){}

    const char* what() const NOEXCEPT override
    {
        return _message.c_str();
    }

private:
    std::string _message;
};

  元組類的使用:this

Values list = {5, "hello"};

for (Value value : list)
{
    std::cout << value << " ";
}

3.2 ByteArray類實現

  該類主要擴展字節的基本操做

class ByteArray : public std::vector<char> {
public:
    ByteArray() = default;

    ByteArray(int32_t size) :
            std::vector<char>(size) {
    }

    ByteArray(const char *buffer, int32_t size) :
            std::vector<char>(buffer, buffer + size) {
    }

    ByteArray(const std::string &str) :
            std::vector<char>(str.size()) {
        memcpy(data(), str.c_str(), str.size());
    }

    std::string ToStdString() const {
        std::string result(this->cbegin(), this->cend());

        return result;
    }

    ByteArray &Concat(const ByteArray &buffer2) {
        size_t oldSize = size();
        size_t newSize = oldSize + buffer2.size();
        resize(newSize);
        memcpy(this->data() + oldSize, buffer2.data(), buffer2.size());

        return *this;
    }

    ByteArray operator+(const ByteArray &buffer2) const {
        ByteArray buffer1(this->size() + buffer2.size());
        memcpy(buffer1.data(), this->data(), this->size());
        memcpy(buffer1.data() + this->size(), buffer2.data(), buffer2.size());

        return buffer1;
    }
};

3.3 ByteArrayReader和ByteArrayWriter類實現

  ByteArrayReader:實現二進制流到指定類型T的轉換,即將ByteArrray寫入到類型Tbuff中

  ByteArrayWriter:將T類型的Buff寫到ByteArray中

  具體代碼實現以下:

#pragma once

#include "ByteArray.h"

#include <stdint.h>

class IODevice
{
public:
    enum class SeekMode
    {
        Set,
        Forward,
        Backward
    };
};

class ByteArrayWriter : public IODevice
{
public:
    ByteArrayWriter()
    {
    }

    template <class T>
    int32_t Write(const T* buffer, int32_t size)
    {
        int32_t nWriteSize = sizeof(T) * size;
        ByteArray buffer2((const char *)buffer, nWriteSize);

        _bytes.Concat(buffer2);

        return nWriteSize;
    }

    template <class T>
    int32_t Write(const T& value)
    {
        return Write((T *)&value, 1);
    }

    int32_t Write(const ByteArray& byteArray)
    {
        _bytes.Concat(byteArray);

        return byteArray.size();
    }

    ByteArray ToByteArray() const{
        return _bytes;
    }

    int32_t Tell() const{
        return _bytes.size();
    }

private:
    ByteArray _bytes;
};

class ByteArrayReader : public IODevice
{
public:
    ByteArrayReader(const ByteArray& byteArray):
        _bytes(byteArray), _pos(0)
        {

        }

    template <class T>
    int32_t Read(T *buff, int32_t count)
    {
        int nSizeToRead = sizeof(T) * count;

        if(_pos >= _bytes.size())
        {
            return 0;
        }
        else if (_bytes.size() - _pos < nSizeToRead)
        {
            nSizeToRead = _bytes.size() - _pos;
        }

        memcpy(buff, _bytes.data() + _pos, nSizeToRead);
        _pos += nSizeToRead;
        return nSizeToRead;
    }

    template <class T>
    T Read()
    {
        T t;
        int32_t nSize = Read(&t, 1);
        return t;
    }

    ByteArray Read(int32_t size)
    {
        int nSizeToRead = size;

        if(_pos >= _bytes.size())
        {
            return 0;
        }
        else if (_bytes.size() - _pos < nSizeToRead)
        {
            nSizeToRead = _bytes.size() - _pos;
        }

        ByteArray byteArray(_bytes.data() + _pos, nSizeToRead);
        _pos += nSizeToRead;

        return byteArray;
    }

    int32_t Tell() const
    {
        return _pos;
    }

    void Seek(SeekMode mode, int32_t size)
    {
        if(mode == SeekMode::Set)
        {
            _pos = size;
        }
        else if(mode == SeekMode::Forward)
        {
            _pos += size;
        }
        else if(mode == SeekMode::Backward)
        {
            _pos -= size;
        }
    }
private:
    ByteArray _bytes;
    int32_t _pos;
};
View Code

3.4 各數據類型讀寫控制類實現

  在進行數據序列化和反序列化的過程當中都必須根據數據類型進行指定數據類型的讀寫操做,咱們用兩個map其類型和Writeable類的映射關係:

std::map<Value::Type, int32_t> CodeToTypeMap;
std::map<int32_t, std::shared_ptr<IWriteble>> WriterMap;

CodeToTypeMap.insert({ Value::Type::Int32, 5 });
CodeToTypeMap.insert({ Value::Type::String, 9 });

WriterMap.insert({ 5, std::shared_ptr<IWriteble>(new Int32Writeable) });
WriterMap.insert({ 9, std::shared_ptr<IWriteble>(new StringWriteable) });

  代碼實現:

class IWriteble
{
public:
    virtual int32_t Write(ByteArrayWriter& Writer, const Value& value) = 0;
    virtual int32_t Read(ByteArrayReader& Reader, Value& value) = 0;
};

class Int32Writeable : public IWriteble
{
public:
    Int32Writeable(){}

    int32_t Write(ByteArrayWriter& Writer, const Value& value) override
    {
        int32_t nValue = value.GetInt32Value();
        return Writer.Write<int32_t>(nValue);
    }

    int32_t Read(ByteArrayReader& Reader, Value& value) override
    {
        int32_t nValue = Reader.Read<int32_t>();
        value.SetInt32Value(nValue);

        return sizeof(int32_t);
    }
};

class StringWriteable : public IWriteble
{
public:
    StringWriteable(){}

    int32_t Write(ByteArrayWriter& Writer, const Value& value) override
    {
        std::string stringValue = value.GetStringValue();
        Writer.Write(stringValue.size());
        Writer.Write(stringValue.c_str(), stringValue.size());

        return sizeof(int32_t) + stringValue.size();
    }
    
    int32_t Read(ByteArrayReader& Reader, Value& value) override
    {
        // 對於string類型,前4個字節爲字符串的長度,後面爲字符串的內容
        int32_t nSize = Reader.Read<int32_t>();
        ByteArray byteArray = Reader.Read(nSize);
        value.SetStringValue(byteArray.ToStdString());

        return sizeof(int32_t) + byteArray.size(); // 注意這個位置不該該直接寫nSize
    }
};
View Code

3.5 序列化和反序列化函數實現

class DataPachage
{
public:
    DataPachage()
    {
        CodeToTypeMap.insert({ Value::Type::Int32, 5 });
        CodeToTypeMap.insert({ Value::Type::String, 9 });

        WriterMap.insert({ 5, std::shared_ptr<IWriteble>(new Int32Writeable) });
        WriterMap.insert({ 9, std::shared_ptr<IWriteble>(new StringWriteable) });
    }

    ByteArray Serialize(const Values& values)
    {
        ByteArrayWriter Writer;
        for (Value value : values)
        {
            Value::Type type = value.GetValueType();
            int32_t code = CodeToTypeMap[type];
            std::shared_ptr<IWriteble> pInt32Writer = std::shared_ptr<IWriteble>(new Int32Writeable());
            pInt32Writer->Write(Writer, code);
            std::shared_ptr<IWriteble> Writeable = WriterMap[code];
            Writeable->Write(Writer, value);
        }

        return Writer.ToByteArray();
    }

    Values DeSerialize(const ByteArray& byteArray)
    {
        Values values;
        int32_t i = 0;
        ByteArrayReader Reader(byteArray);
        int32_t pos = 0;
        while (( pos = Reader.Tell()) < byteArray.size())
        {
            std::shared_ptr<IWriteble> pInt32Writer = std::shared_ptr<IWriteble>(new Int32Writeable());
            Value value;
            pInt32Writer->Read(Reader, value);
            std::shared_ptr<IWriteble> Writeable = WriterMap[value.GetInt32Value()];
            Writeable->Read(Reader, value);
            values.push_back(value);
        }
        
        return values;
    }

private:
    std::map<Value::Type, int32_t> CodeToTypeMap;
    std::map<int32_t, std::shared_ptr<IWriteble>> WriterMap;
};

3.6 測試

#include "stdio.h"

#include "Serialize.h"

int main()
{
    Values list = {5, "hello"};
    
    std::cout << "序列化前Values值:" << std::endl;
    for (Value value : list)
    {
        std::cout << value << " ";
    }
    std::cout << std::endl;
    DataPachage data;
    ByteArray bytes = data.Serialize(list);

    Values list1 = data.DeSerialize(bytes);
    
    std::cout << "反序列化獲得Values值:" << std::endl;
    for (Value value : list1)
    {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}

  附:

#pragma once

#include <vector>
#include <string>
#include <cstring>
#include <stdint.h>

class ByteArray : public std::vector<char> {
public:
    ByteArray() = default;

    ByteArray(int32_t size) :
            std::vector<char>(size) {
    }

    ByteArray(const char *buffer, int32_t size) :
            std::vector<char>(buffer, buffer + size) {
    }

    ByteArray(const std::string &str) :
            std::vector<char>(str.size()) {
        memcpy(data(), str.c_str(), str.size());
    }

    std::string ToStdString() const {
        std::string result(this->cbegin(), this->cend());

        return result;
    }

    ByteArray &Concat(const ByteArray &buffer2) {
        size_t oldSize = size();
        size_t newSize = oldSize + buffer2.size();
        resize(newSize);
        memcpy(this->data() + oldSize, buffer2.data(), buffer2.size());

        return *this;
    }

    ByteArray operator+(const ByteArray &buffer2) const {
        ByteArray buffer1(this->size() + buffer2.size());
        memcpy(buffer1.data(), this->data(), this->size());
        memcpy(buffer1.data() + this->size(), buffer2.data(), buffer2.size());

        return buffer1;
    }
};


    
ByteArray.h
#pragma once

#include "ByteArray.h"

#include <stdint.h>

class IODevice
{
public:
    enum class SeekMode
    {
        Set,
        Forward,
        Backward
    };
};

class ByteArrayWriter : public IODevice
{
public:
    ByteArrayWriter()
    {
    }

    template <class T>
    int32_t Write(const T* buffer, int32_t size)
    {
        int32_t nWriteSize = sizeof(T) * size;
        ByteArray buffer2((const char *)buffer, nWriteSize);

        _bytes.Concat(buffer2);

        return nWriteSize;
    }

    template <class T>
    int32_t Write(const T& value)
    {
        return Write((T *)&value, 1);
    }

    int32_t Write(const ByteArray& byteArray)
    {
        _bytes.Concat(byteArray);

        return byteArray.size();
    }

    ByteArray ToByteArray() const{
        return _bytes;
    }

    int32_t Tell() const{
        return _bytes.size();
    }

private:
    ByteArray _bytes;
};

class ByteArrayReader : public IODevice
{
public:
    ByteArrayReader(const ByteArray& byteArray):
        _bytes(byteArray), _pos(0)
        {

        }

    template <class T>
    int32_t Read(T *buff, int32_t count)
    {
        int nSizeToRead = sizeof(T) * count;

        if(_pos >= _bytes.size())
        {
            return 0;
        }
        else if (_bytes.size() - _pos < nSizeToRead)
        {
            nSizeToRead = _bytes.size() - _pos;
        }

        memcpy(buff, _bytes.data() + _pos, nSizeToRead);
        _pos += nSizeToRead;
        return nSizeToRead;
    }

    template <class T>
    T Read()
    {
        T t;
        int32_t nSize = Read(&t, 1);
        return t;
    }

    ByteArray Read(int32_t size)
    {
        int nSizeToRead = size;

        if(_pos >= _bytes.size())
        {
            return 0;
        }
        else if (_bytes.size() - _pos < nSizeToRead)
        {
            nSizeToRead = _bytes.size() - _pos;
        }

        ByteArray byteArray(_bytes.data() + _pos, nSizeToRead);
        _pos += nSizeToRead;

        return byteArray;
    }

    int32_t Tell() const
    {
        return _pos;
    }

    void Seek(SeekMode mode, int32_t size)
    {
        if(mode == SeekMode::Set)
        {
            _pos = size;
        }
        else if(mode == SeekMode::Forward)
        {
            _pos += size;
        }
        else if(mode == SeekMode::Backward)
        {
            _pos -= size;
        }
    }
private:
    ByteArray _bytes;
    int32_t _pos;
};
IODevice.h
#pragma once

#include <stdint.h>
#include <exception>
#include <string>
#include <iostream>

#ifdef WIN32
#define NOEXCEPT
#else
#define NOEXCEPT noexcept
#endif

class TypeMismatchException : public std::exception
{
public:
    TypeMismatchException(const std::string& message) :
        _message(message){}

    const char* what() const NOEXCEPT override
    {
        return _message.c_str();
    }

private:
    std::string _message;
};

class Value {
public:
    enum class Type {
        Invalid,
        Boolean,
        Character,
        Int8,
        Int16,
        Int32,
        Int64,
        Float,
        Double,
        String
    };

    union InnerValue {
        bool booleanValue;
        char characterValue;
        int8_t int8Value;
        int16_t int16Value;
        int32_t int32Value;
        int64_t int64Value;
        float floatValue;
        double doubleValue;
    };

    Value() : _type(Type::Invalid) {
    }

    Value(bool value) : _type(Type::Boolean) {
        _value.booleanValue = value;
    }

    Value(char value) : _type(Type::Character) {
        _value.characterValue = value;
    }

    Value(int8_t value) : _type(Type::Int8) {
        _value.int8Value = value;
    }

    Value(int16_t value) : _type(Type::Int16) {
        _value.int16Value = value;
    }

    Value(int32_t value) : _type(Type::Int32) {
        _value.int32Value = value;
    }

    Value(int64_t value) : _type(Type::Int64) {
        _value.int64Value = value;
    }

    Value(float value) : _type(Type::Float) {
        _value.floatValue = value;
    }

    Value(double value) : _type(Type::Double) {
        _value.doubleValue = value;
    }

    Value(const std::string& value) : _type(Type::String) {
        _stringValue = value;
    }

    Value(const char* value) : Value(std::string(value)) {
    }

    bool ToBoolean() const {
        if ( _type != Type::Boolean ) {
            throw TypeMismatchException("The type of value is not boolean");
        }
    }

    int8_t ToInt8() const {
        if ( _type != Type::Int8 ) {
            throw TypeMismatchException("The type of value is not int8");
        }

        return _value.int8Value;
    }

    int16_t ToInt16() const {
        if ( _type != Type::Int16 ) {
            throw TypeMismatchException("The type of value is not int16");
        }

        return _value.int16Value;
    }

    int32_t ToInt32() const {
        if ( _type != Type::Int32 ) {
            throw TypeMismatchException("The type of value is not int32");
        }

        return _value.int32Value;
    }

    int64_t ToInt64() const {
        if ( _type != Type::Int64 ) {
            throw TypeMismatchException("The type of value is not int64");
        }

        return _value.int64Value;
    }

    char ToCharacter() const {
        if ( _type != Type::Character ) {
            throw TypeMismatchException("The type of value is not character");
        }

        return _value.characterValue;
    }

    const std::string& ToString() const {
        if ( _type != Type::String ) {
            throw TypeMismatchException("The type of value is not string");
        }

        return _stringValue;
    }
    
    friend std::ostream& operator<<(std::ostream& os, const Value& value)
    {
        if (value._type == Type::String)
        {
            os << "value:" << value._stringValue;
        }
        else if (value._type == Type::Int32)
        {
            os << "value:" << value._value.int32Value;
        }
        else if (value._type == Type::Double)
        {
            os << "value:" << value._value.doubleValue;
        }
        return os;
    } 

    // 如下以int32和string爲例進行測試
    void SetInt32Value(int32_t value)
    {
        _type = Type::Int32;
        _value.int32Value = value;
    }

    void SetStringValue(std::string value)
    {
        _type = Type::String;
        _stringValue = value;
    }

    int32_t GetInt32Value() const {return _value.int32Value;}
    std::string GetStringValue() const {return _stringValue;}

    Type GetValueType() const {return _type;}

private:
    Type _type;
    InnerValue _value;
    std::string _stringValue;
};

#include <vector>
class Values : public std::vector<Value>
{
public:
    Values() = default;
    Values(std::initializer_list<Value> list) : std::vector<Value>(list)
    {
    }

    Value& operator[](size_t index) {
        return std::vector<Value>::operator[](index);
    }

    const Value& operator[](size_t index) const {
        return std::vector<Value>::operator[](index);
    }
};
Values.h
#pragma once

#include "IODevice.h"
#include "Values.h"

class IWriteble
{
public:
    virtual int32_t Write(ByteArrayWriter& Writer, const Value& value) = 0;
    virtual int32_t Read(ByteArrayReader& Reader, Value& value) = 0;
};

class Int32Writeable : public IWriteble
{
public:
    Int32Writeable(){}

    int32_t Write(ByteArrayWriter& Writer, const Value& value) override
    {
        int32_t nValue = value.GetInt32Value();
        return Writer.Write<int32_t>(nValue);
    }

    int32_t Read(ByteArrayReader& Reader, Value& value) override
    {
        int32_t nValue = Reader.Read<int32_t>();
        value.SetInt32Value(nValue);

        return sizeof(int32_t);
    }
};

class StringWriteable : public IWriteble
{
public:
    StringWriteable(){}

    int32_t Write(ByteArrayWriter& Writer, const Value& value) override
    {
        std::string stringValue = value.GetStringValue();
        Writer.Write(stringValue.size());
        Writer.Write(stringValue.c_str(), stringValue.size());

        return sizeof(int32_t) + stringValue.size();
    }
    
    int32_t Read(ByteArrayReader& Reader, Value& value) override
    {
        // 對於string類型,前4個字節爲字符串的長度,後面爲字符串的內容
        int32_t nSize = Reader.Read<int32_t>();
        ByteArray byteArray = Reader.Read(nSize);
        value.SetStringValue(byteArray.ToStdString());

        return sizeof(int32_t) + byteArray.size(); // 注意這個位置不該該直接寫nSize
    }
};


#include <map>
#include <memory>
/*std::map<Value::Type, int32_t> CodeToTypeMap =
{
    {Value::Type::Int32, 5},
    {Value::Type::String, 9}
};

// 根據數據類型獲得對應的IWriteble
std::map<int32_t, std::shared_ptr<IWriteble>> WriterMap =
{
    {5, std::shared_ptr<IWriteble>(new Int32Writeable)},
    {9, std::shared_ptr<IWriteble>(new StringWriteable)}
};*/

//static std::map<int32_t, IWriteble*> WriterMap =
//{
//    {5, new Int32Writeable()},
//    {9, new StringWriteable()}
//};


class DataPachage
{
public:
    DataPachage()
    {
        CodeToTypeMap.insert({ Value::Type::Int32, 5 });
        CodeToTypeMap.insert({ Value::Type::String, 9 });

        WriterMap.insert({ 5, std::shared_ptr<IWriteble>(new Int32Writeable) });
        WriterMap.insert({ 9, std::shared_ptr<IWriteble>(new StringWriteable) });
    }

    ByteArray Serialize(const Values& values)
    {
        ByteArrayWriter Writer;
        for (Value value : values)
        {
            Value::Type type = value.GetValueType();
            int32_t code = CodeToTypeMap[type];
            std::shared_ptr<IWriteble> pInt32Writer = std::shared_ptr<IWriteble>(new Int32Writeable());
            pInt32Writer->Write(Writer, code);
            std::shared_ptr<IWriteble> Writeable = WriterMap[code];
            Writeable->Write(Writer, value);
        }

        return Writer.ToByteArray();
    }

    Values DeSerialize(const ByteArray& byteArray)
    {
        Values values;
        int32_t i = 0;
        ByteArrayReader Reader(byteArray);
        int32_t pos = 0;
        while (( pos = Reader.Tell()) < byteArray.size())
        {
            std::shared_ptr<IWriteble> pInt32Writer = std::shared_ptr<IWriteble>(new Int32Writeable());
            Value value;
            pInt32Writer->Read(Reader, value);
            std::shared_ptr<IWriteble> Writeable = WriterMap[value.GetInt32Value()];
            Writeable->Read(Reader, value);
            values.push_back(value);
        }
        
        return values;
    }

private:
    std::map<Value::Type, int32_t> CodeToTypeMap;
    std::map<int32_t, std::shared_ptr<IWriteble>> WriterMap;
};
Serialize.h
#include "stdio.h"

#include "Serialize.h"

int main()
{
    Values list = {5, "hello"};
    
    std::cout << "序列化前Values值:" << std::endl;
    for (Value value : list)
    {
        std::cout << value << " ";
    }
    std::cout << std::endl;
    DataPachage data;
    ByteArray bytes = data.Serialize(list);

    Values list1 = data.DeSerialize(bytes);
    
    std::cout << "反序列化獲得Values值:" << std::endl;
    for (Value value : list1)
    {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}
main.cpp
相關文章
相關標籤/搜索