0

考虑以下 sensor.proto 文件,该文件使用重复字段来初始化多条消息。

syntax = "proto3";

package HUBSensors;

message Device {
    string name = 1;
    int32 id = 2;

    message Sensor {
        string name = 1;
        double temperature = 2;
        int32 humidity = 3;

        enum SwitchLevel {
            CLOSED = 0;
            OPEN = 1;
        }

        SwitchLevel door = 4;
    }

    repeated Sensor sensors = 3;
}

现在我想将一些随机数据序列化到一个文件中。例如,我将拥有一个带有多个传感器的设备,因此 proto 中的重复文件。我使用以下代码。

inline void serialize_to_file( const std::string &fileName )
{
    HUBSensors::Device device;

    device.set_name("HUB");
    device.set_id(1234);

    device.add_sensors()->set_name("Laboratory");
    device.add_sensors()->set_temperature(23.3);
    device.add_sensors()->set_humidity(2);
    device.add_sensors()->set_door(HUBSensors::Device_Sensor_SwitchLevel_OPEN);

    device.add_sensors()->set_name("Chml Laboratory");
    device.add_sensors()->set_temperature(2.3);
    device.add_sensors()->set_humidity(5);
    device.add_sensors()->set_door(HUBSensors::Device_Sensor_SwitchLevel_CLOSED);

    device.add_sensors()->set_name("GU Laboratory");
    device.add_sensors()->set_temperature(8.3);
    device.add_sensors()->set_humidity(2);
    device.add_sensors()->set_door(HUBSensors::Device_Sensor_SwitchLevel_CLOSED);


    std::ofstream ofs(fileName, std::ios_base::out | std::ios_base::binary );
    device.SerializeToOstream( &ofs );
    google::protobuf::ShutdownProtobufLibrary();
}

要解析数据并打印出结果,我使用以下命令:

inline void parse_from_file( const std::string &fileName )
{
    HUBSensors::Device device;
    std::ifstream myFile;
    myFile.exceptions( std::ifstream::badbit );

    try {
        myFile.open(fileName);

        while ( myFile.good() )
        {
            device.ParseFromIstream( &myFile );

            //std::cout << device.sensors_size() << std::endl;

            std::cout << "Device Name : " << device.name() << std::endl;
            std::cout << "^^^^^^" << std::endl;
            for ( size_t i = 0; i < device.sensors_size(); i+=4)
            {
                std::cout << "Sensors Name : " << device.sensors(i).name() << std::endl;
                std::cout << "Temperature : " << device.sensors(i+1).temperature() << std::endl;
                std::cout << "Humidity : " << device.sensors(i+2).humidity() << std::endl;
                std::cout << " Door Status :  " << device.sensors(i+3).door() << std::endl;
                std::cout << "^^^^^^" << std::endl;
            }
        }
    }
    catch ( const std::ifstream::failure &e )
    {
        std::cerr << "Error Occurred when accessing the file" << std::endl;
        std::cout << e.what() << std::endl;
    }
    myFile.close();
    google::protobuf::ShutdownProtobufLibrary();
}

重现结果的主文件:

#include <iostream>
#include <fstream>
#include <stdexcept>

#include "sensor.pb.h"


int main() {

    GOOGLE_PROTOBUF_VERIFY_VERSION;

    const std::string fileName = "./device.data";

    serialize_to_file( fileName );
    parse_from_file( fileName );

    return 0;
}

遍历整个传感器大小并获得正确的索引以显示适当的字段似乎并不直观。即使通过检查

std::cout << device.sensors_size() << std::endl;

将输出感觉不正确的尺寸 12,或

std::cout << decice.sensors(2).name() << std::endl;

不会输出任何内容,因为它位于不正确的索引中。使用 libprotobuf 定义重复字段以更好地进行序列化/反序列化的更好方法是什么。


编辑:正如答案所暗示的,序列化到文件应该是


inline void serialize_to_file( const std::string &fileName )
{
    HUBSensors::Device device;

    device.set_name("HUB");
    device.set_id(1234);

    auto sensor1 = device.add_sensors();
    auto sensor2 = device.add_sensors();
    auto sensor3 = device.add_sensors();

    sensor1->set_name("Laboratory");
    sensor1->set_temperature(23.3);
    sensor1->set_humidity(2);
    sensor1->set_door(HUBSensors::Device_Sensor_SwitchLevel_CLOSED);

    sensor2->set_name("GU Laboratory");
    sensor2->set_temperature(44.3);
    sensor2->set_humidity(4);
    sensor2->set_door(HUBSensors::Device_Sensor_SwitchLevel_OPEN);

    sensor3->set_name("Chml Laboratory");
    sensor3->set_temperature(13.345);
    sensor3->set_humidity(6);
    sensor3->set_door(HUBSensors::Device_Sensor_SwitchLevel_CLOSED);

    std::ofstream ofs(fileName, std::ios_base::out | std::ios_base::binary );
    device.SerializeToOstream( &ofs );
    google::protobuf::ShutdownProtobufLibrary();
}
4

1 回答 1

3

代替

    device.add_sensors()->set_name("Laboratory");
    device.add_sensors()->set_temperature(23.3);
    device.add_sensors()->set_humidity(2);
    device.add_sensors()->set_door(HUBSensors::Device_Sensor_SwitchLevel_OPEN);

你应该写

    auto sensor = device.add_sensors();
    sensor->set_name("Laboratory");
    sensor->set_temperature(23.3);
    sensor->set_humidity(2);
    sensor->set_door(HUBSensors::Device_Sensor_SwitchLevel_OPEN);

这样,您将拥有 3 个传感器,我想这是您的意图,并且所有传感器都将拥有每个数据成员集。

于 2020-01-08T15:27:16.817 回答