Supposons, votre protobuf message
ressemble à ceci:
message Object
{
... = 1;
... = 2;
... = 3;
}
Ensuite, dans le même fichier introduisons 1 plus message
qui est une collection de ces Object
s.
message Objects
{
repeated Object array = 1;
}
Par conséquent, lorsque vous avez beaucoup d'éléments, vous pouvez simplement utiliser le Objects
et utiliser SerializeAsString()
sur Objects
lui-même. Cela permettra d'économiser vos efforts de série individuelle Object
séparément et en mettant votre propre délimiteur à la main. Vous pouvez sérialiser tous les Object
en utilisant une instance unique de Objects
.
Avec cette approche, vous êtes déléguer tous les travaux de sérialisation & d'analyse également à la bibliothèque Protobuf. Je l'utilise dans mon projet et ça fonctionne comme un charme. En outre, l'utilisation judicieuse de Objects
permettra également d'éviter de faire des copies supplémentaires de Object
. Vous pouvez ajouter des éléments à cela et accéder à l'aide de l'indexation. Les champs repeated
de protobufs sont conformes à C++ 11, vous pouvez donc l'utiliser avec des itérateurs ou une boucle for
améliorée.
important de noter que, lorsque vous stockez la sortie du Objects::SerializeAsString()
dans un fichier, vous devez d'abord saisir la longueur de cette string
suivi de la chaîne sérialisée réelle. Pendant la lecture, vous pouvez lire la longueur en premier suivie par le nombre total d'octets. Pour la facilité d'utilisation, je l'ai étendu la std::fstream
et surcharge les méthodes suivantes:
struct fstreamEncoded : std::fstream
{
// other methods
void // returns `void` to avoid multiple `<<` in a single line
operator<< (const string& content)
{ // below casting would avoid recursive calling of this method
// adding `length() + 1` to include the protobuf's last character as well
static_cast<std::fstream&>(*this) << (content.length() + 1) << "\n" << content << std::endl;
}
string
getline()
{
char length_[20] = {};
std::istream::getline(length_, sizeof(length_) - 1);
if(*length_ == 0)
return "";
const size_t length = std::atol(length_); // length of encoded input
string content(length, 0); // resize the `string`
read(&content[0], length); // member of `class istream`
return content;
}
}
Au-dessus est juste une illustration. Vous pouvez suivre en fonction des besoins de votre projet.
Que diriez-vous de préfixer le flux de chaîne avec des informations de longueur? – Arunmu
Je pourrais préfixer un sizeof (int) devant chaque chaîne. On dirait que ça devrait marcher. Je vais essayer de poster des résultats si cela va fonctionner – Mugen