8

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++ です。

お時間をいただきありがとうございます!

4

3 に答える 3

3

読み取りの失敗は、ファイルが O_BINARY で読み取り用に開かれていないためでした - ファイルの開き方をこれに変更すると、動作します:

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

根本的な原因は、「 read() はファイルから数バイトしか読み取らない」と同じです。同じ方法でファイルを開く protobuf ドキュメントの例に従っている可能性が非常に高いですが、ファイル内の特殊文字にヒットすると、Windows での解析が停止します。

また、ライブラリの最近のバージョンでは、protobuf::util::ParseDelimitedFromCodedStreamサイズとペイロードのペアの読み取りを簡素化するために使用できます。

...質問は古いかもしれませんが、問題はまだ存在しており、この答えはほぼ確実に元の問題に対する修正です。

于 2017-10-03T14:18:43.517 に答える
-1

使用してみてください

codedinput->readRawBytesの海底ReadString

dl.ParseFromArrayそれ以外のParseFromString

プロトコルバッファにあまり精通していReadStringませんが、タイプのフィールドのみを読み取る可能性がありstrineます。

于 2012-09-25T12:37:55.273 に答える