2

I want to read a binary file using Cpp, and its type is using MsgPack. I'm not familiar with MsgPack and I try to read binary file fist and push in MsgPack. It doesn't work. It just gets the first number again and again. Can anyone help? Thanks a lot.

#include <bits/stdc++.h>
#include <msgpack.hpp>
using namespace std;

int main()
{
    std::ifstream ifs("input.txt", std::ifstream::in);
    std::stringstream buffer;
    buffer << ifs.rdbuf();
    msgpack::unpacked upd;
    msgpack::unpack(upd, buffer.str().data(), buffer.str().size());
    std::cout << upd.get() << std::endl;
    return 0;
}

Which it can just get the first number "3".

I'm hoping to get number:

3
[3 6 7 5 3 5]
[6 2 9 1 2 7]
[0 9 3 6 0 6]

And here is the input binary file.

3 Answers3

2

msgpack::unpack() unpacks the first MessagePack formatted data. I think that 3 means the number of following arrays.

In this case offset is useful. See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_unpacker#client-controls-a-buffer

Here is the code reading the first MessagePack data 3 as the counter. And then 3 times call msgpack::unpack() to unpack each array. During that process, the variable offset is updated.

#include <iostream>
#include <fstream>
#include <msgpack.hpp>

int main()
{
    std::ifstream ifs("input.txt");
    std::string buffer((std::istreambuf_iterator<char>(ifs)),
                        std::istreambuf_iterator<char>());
    msgpack::unpacked upd;
    std::size_t offset = 0;
    msgpack::unpack(upd, buffer.data(), buffer.size(), offset);
    std::size_t count = upd.get().as<std::size_t>();
    std::cout << count << std::endl;
    for (std::size_t i = 0; i != count; ++i) {
        msgpack::unpack(upd, buffer.data(), buffer.size(), offset);
        std::cout << upd.get() << std::endl;
    }

}

I believe that this is the approach based on your original code.

Takatoshi Kondo
  • 2,569
  • 14
  • 25
  • your solution based on your assumption that first number is a number of following arrays. What if it is incorrect and @Gavin Lee just wanted to parse 4 independence messages? At least you can check if `offset` is still less than `buffer.size()` in your for loop. – JustRufus Mar 18 '17 at 07:45
1

Your code unpacks only one msgpack message (first one, which is 3) but actually your file contains 4 messages. So you can use msgpack::unpacker class to unpack all messages one by one.

int main()
{
    std::ifstream ifs("input.txt", std::ifstream::in);
    std::string buffer((std::istreambuf_iterator<char>(ifs)),
                        std::istreambuf_iterator<char>());

    msgpack::unpacker pac;
    pac.reserve_buffer( buffer.size() );
    std::copy( buffer.begin(), buffer.end(), pac.buffer() );
    pac.buffer_consumed( buffer.size() );

    msgpack::object_handle oh;
    while ( pac.next(oh) ) {
        msgpack::object msg = oh.get();
        std::cout << msg << std::endl;
    }
    return 0;
}

P.S. Read this and stop using #include <bits/stdc++.h>.

Community
  • 1
  • 1
JustRufus
  • 462
  • 1
  • 5
  • 10
0

i think problem here : buffer.str().size() you can try

buffer.str().length() 

or strlen(buffer.str().data().c_str());

Denis
  • 3
  • 3
  • both std::string::size and std::string::length are 'synonyms'. http://en.cppreference.com/w/cpp/string/basic_string/size – JustRufus Mar 16 '17 at 21:11