序列化和反序列化实现

1.什么是序列化?程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入文件或是将其传输到网络中的另一台计算机上以实现通讯。这个将程序数据转换成能被存储并传输的格式的过程被称

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

1. 什么是序列化?

  程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入文件或是将其传输到网络中的另一台计算机上以实现通讯。这个将程序数据转换成能被存储并传输的格式的过程被称为序列化(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;
};

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

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/120092.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • CGLib简单入门

    CGLib简单入门一、CGlib简介        CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。 当然这些实际的功能是asm所提供的,asm又是什么?Java字节码操控框架,具体是什么大家可以上网查一查,毕竟我们这里所要讨论的是cglib。cglib就是封装了asm,简化了asm的操作,实现了在运行期动态生成新的class。 可能大家还感觉不到它的

  • python set大小_python set集合

    python set大小_python set集合集合set可变的无序的不重复的元素集合set定义初始化set()生成一个空集合set(iterable)可通过可迭代对象生产一个新的集合s1=set()s2=set(range(5))s3=set(list(range(10)))s4={}#这是字典的定义方法s5={9,10,11}#sets6={(1,2),3,’a’}s7={[1],(1,),1}#set的元素要…

  • dpkg命令的用法

    dpkg命令的用法dpkg命令的用法dpkg是Debianpackage的简写,为”Debian“操作系统专门开发的套件管理系统,用于软件的安装,更新和移除。所有源自"Debian"的Linux的发行版都使用dpkg,  例如"Ubuntu" 阅读目录 安装软件列出与该包先关联的文件显示包的版本移除软件(保留配置)移除软件(不保留配置)查找包的详细信息列出deb包的内容 安装软件命令:dpkg-i&…

  • axios上传文件以及遇到的问题

    axios上传文件以及遇到的问题axios上传文件以及遇到的问题1,这里上传文件使用的是elementUI的上传,也用原生的input上传写了,但是没有时间做多文件上传,下面会把代码贴出。2,这里上传文件我是先获取OSS权限和上传路径,然后再上传。但是权限获取成功后,上传到阿里云服务器时,OPTION请求报403。原因是项目中axios设置了拦截器,添加了config配置,但是在axios发送OPTION测试接口是否有权限访…

  • js常见问题

    js常见问题

  • eclipse中配置jdk

    eclipse中配置jdkwindow->preference->java->installjres->add->standardvm->设置好相应的jrehomeeclipse的实验版本:Version:4.3.0.v20130605-20001、点击eclipse菜单栏的window下拉菜单选中preference2、点击…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号