Я новичок в пакете сообщений, и я пытаюсь взять хеш в perl, сериализовать его с помощью пакета сообщений, записать его в файл, передать его в код на С ++, где файл читается и десериализуется в карту.
Мой Perl-код для генерации файла (примечание — я добавил дополнительную часть, чтобы проверить, могу ли я прочитать файл обратно и правильно десериализовать его в Perl, хотя мне это не нужно):
#! perl
use strict;
use warnings;
use Data::MessagePack;
my %hTestHash = ('AAAAAA' => '20020101',
'BBBBBB' => '20030907');
my $packed = Data::MessagePack->pack(\%hTestHash);
open my $fh, '>', 'splodge.bin' or die "Failed to open slodge.bin for write: $!";
print $fh $packed;
close $fh;
open my $fh2, '<', 'splodge.bin' or die "Failed to open slodge.bin for read: $!";
local $/;
my $file = <$fh2>;
my $hrTest = Data::MessagePack->unpack($file);
Мой код на С ++ для десериализации:
#include "msgpack.hpp"#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
int main(void)
{
// Deserialize the serialized data.
std::ifstream ifs("splodge.bin", std::ifstream::in);
std::stringstream buffer;
buffer << ifs.rdbuf();
msgpack::unpacked upd;
msgpack::unpack(&upd, buffer.str().data(), buffer.str().size());
msgpack::object obj = upd.get();
std::map<std::string, std::string> output_map;
msgpack::convert(output_map, obj);
string date = output_map.at("AAAAAA");
return 0;
}
Это создает 2-элементную карту в output_map
, но он содержит только значения мусора — моя программа вылетает на output_map.at()
с
{"▒▒▒▒▒▒"=>"▒▒▒▒▒▒▒▒", "▒▒▒▒▒▒"=>"▒▒▒▒▒▒▒▒"}
terminate called after throwing an instance of 'std::out_of_range'
what(): map::at
Aborted
Я не смог найти каких-либо примеров этого конкретного варианта использования и изо всех сил пытался понять, что же не так — это проблема в конце сериализации или (кажется более вероятной) в конце десериализации?
РЕДАКТИРОВАТЬ: Спасибо @ SinanÜnür за указание на мою ошибку, которую я сейчас обновил в этом вопросе. Это не меняет того факта, что хеш заполняется значениями мусора, поэтому выдается одно и то же исключение независимо от того, какой ключ ищется.
Наконец-то удалось заставить его работать с сочетанием правильного чтения двоичных файлов и некоторого манипулирования со странными внутренними типами данных, которые мы имеем.
Функциональный код (который десериализует структуру в Map<string, msgpack::object>
, требующий дополнительного шага десериализации каждого значения, когда это необходимо):
#include "msgpack.hpp"#include "map.h"#include <string>
#include <iostream>
#include <fstream>
void unpack_map(const msgpack::object& o, Map<string,msgpack::object>& results){
ASSERT(o.type == msgpack::type::MAP);
for (msgpack::object_kv *p = o.via.map.ptr, *pend = (o.via.map.ptr + o.via.map.size); p != pend; ++p)
results[p->key.as<string>()] = p->val;
}
int main(void)
{
streampos size;
char * memblock;
ifstream file ("splodge.bin", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
cout << "the entire file content is in memory";
}
else cout << "Unable to open file";
msgpack::unpacked upd;
msgpack::unpack(&upd, memblock, size);
msgpack::object obj = upd.get();
if(obj.type != msgpack::type::MAP) {
cout << ":(" << endl;
} else {
cout << ":)" << endl;
}
cout << "size: " << obj.via.map.size << endl;
Map<string, msgpack::object> objectMap;
unpack_map(obj, objectMap);
msgpack::object val = objectMap["BBBBBB"];
string tmp = string(val.via.raw.ptr, val.via.raw.size);
delete[] memblock;
return 0;
}
где tmp
принимает значение 20030907
Других решений пока нет …