程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入文件或是将其传输到网络中的另一台计算机上以实现通讯。这个将程序数据转换成能被存储并传输的格式的过程被称为序列化(serialization),而它的逆过程被称为反序列化(deserialization)。
简单来说,序列化就是将对象实例的状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它根据流重构对象。这两个过程结合起来,可以轻松地存储和传输数据。
序列化:将对象变成字节流的形式传出去。
反序列化:从字节流恢复成原来的对象。
2. 序列化实现
可以通过将对象转换成json、xml和二进制流的方式实现序列化,鉴于json和xml在不同编程语言中其组包、解包的API接口实现方法的不同,我决定采用通用的二进制流的方式实现序列化。
2.1 类图设计
3. 各个组件代码实现
3.1 元组实现
该元组可以接纳我们自定义的任意类型
数据类型定义:
enum class Type { Invalid, Boolean, Character, Int8, Int16, Int32, Int64, Float, Double, String };
联合体InnerValue定义:联合体的优点在于所有的值共享一篇存储空间,因此不会引起额外的空间存储消耗
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; };
元组类的使用:
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; };