簡體   English   中英

協議緩沖區; 將數據保存到磁盤並加載回問題

[英]Protocol Buffers; saving data to disk & loading back issue

我有一個將Protobuf數據存儲到磁盤的問題。 我使用協議緩沖區通過套接字傳輸數據的應用程序(工作正常),但當我嘗試將數據存儲到磁盤時它失敗。 實際上,保存數據報告沒有問題,但我似乎無法再次正確加載它們。 任何提示都將很高興。

void writeToDisk(DataList & dList)
{
    // open streams
    int fd = open("serializedMessage.pb", O_WRONLY | O_CREAT);
    google::protobuf::io::ZeroCopyOutputStream* fileOutput = new google::protobuf::io::FileOutputStream(fd);
    google::protobuf::io::CodedOutputStream* codedOutput = new google::protobuf::io::CodedOutputStream(fileOutput);

    // save data
    codedOutput->WriteLittleEndian32(PROTOBUF_MESSAGE_ID_NUMBER); // store with message id
    codedOutput->WriteLittleEndian32(dList.ByteSize()); // the size of the data i will serialize
    dList.SerializeToCodedStream(codedOutput); // serialize the data

    // close streams
    delete codedOutput;
    delete fileOutput;

    close(fd);
}

我已經驗證了這個函數里面的數據,dList包含了我期望的數據。 流報告沒有發生錯誤,並且將合理數量的字節寫入磁盤。 (也是文件大小合理)但是當我嘗試回讀數據時,它不起作用。 而且,真正奇怪的是,如果我將更多數據附加到此文件,我可以讀取第一條消息(但不是最后的消息)。

void readDataFromFile()
{   
    // open streams
    int fd = open("serializedMessage.pb", O_RDONLY);
    google::protobuf::io::ZeroCopyInputStream* fileinput = new google::protobuf::io::FileInputStream(fd);
    google::protobuf::io::CodedInputStream* codedinput = new google::protobuf::io::CodedInputStream(fileinput);

    // read back
    uint32_t sizeToRead = 0, magicNumber = 0;
    string parsedStr = "";

    codedinput->ReadLittleEndian32(&magicNumber); // the message id-number i expect
    codedinput->ReadLittleEndian32(&sizeToRead); // the reported data size, also what i expect
    codedinput->ReadString(&parsedstr, sizeToRead)) // the size() of 'parsedstr' is much less than it should (sizeToRead)

    DataList dl = DataList();

    if (dl.ParseFromString(parsedstr)) // fails
    {
        // work with data if all okay
    }

    // close streams
    delete codedinput;
    delete fileinput;
    close(fd);
}

顯然我在這里省略了一些代碼來簡化一切。 作為旁注,我還嘗試將消息序列化為字符串並通過CodedOutputStream保存該字符串。 這也不起作用。 我已經驗證了該字符串的內容,所以我猜罪魁禍首必須是流函數。

這是一個Windows環境,帶有協議緩沖區和Qt的c ++。

感謝您的時間!

我通過從文件描述符切換到fstream,將FileCopyStream切換到OstreamOutputStream來解決了這個問題。

雖然我看過使用前者的例子,但它對我不起作用。

我在google coded_stream標頭中找到了一個很好的代碼示例。 鏈接#1

此外,由於我需要使用協議緩沖區將多個消息序列化到同一個文件,因此這個鏈接很有啟發性。 鏈接#2

出於某種原因,在我實際解析流對象之前,輸出文件不是“完整的”。

讀取失敗是因為沒有打開文件以便使用O_BINARY進行讀取 - 將文件更改為打開並且它可以正常工作:

int fd = open("serializedMessage.pb", O_RDONLY | O_BINARY);

根本原因與此處相同:“ read()僅從文件中讀取幾個字節 ”。 您很可能在protobuf文檔中跟隨一個示例,它以相同的方式打開文件,但是當它遇到文件中的特殊字符時,它會在Windows上停止解析。

此外,在更新版本的庫中,您可以使用protobuf::util::ParseDelimitedFromCodedStream來簡化讀取大小+有效負載對。

......問題可能很古老,但問題仍然存在,這個答案幾乎可以肯定是對原始問題的解決。

試着用

codedinput->readRawBytes ReadString insead

dl.ParseFromArray而不是ParseFromString

不太熟悉協議緩沖區,但ReadString可能只讀取strine類型的strine

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM