Как распаковать файл msgpack?
Я записываю данные в формате msgpack в файл. При написании я просто использую fbuffer C API. Как в (я чередовал всю обработку ошибок для примера):
FILE *fp = fopen(filename, "ab");
msgpack_packer pk;
msgpack_packer_init(pk, fp, msgpack_fbuffer_write);
msgpack_pack_int(pk, 42);
// more data ...
Как мне прочитать этот файл обратно? Все примеры, которые я нашел, предполагают, что данные находятся в памяти, однако мои файлы занимают до 5 ГБ, не совсем хорошая идея, чтобы полностью хранить их в памяти. Также я не хочу читать кусками сам. В конце концов, я не знаю, как долго объекты msgpack, так что есть вероятность, что в моем буфере окажется половина целого числа.
Может ли распаковка msgpack как-то считывать с диска напрямую? Или есть какой-то стандартный шаблон для этого?
2 ответа
Вместо этого вы можете рассмотреть возможность использования "msgpack_unpacker", что, по-видимому, является официальным способом, которым MessagePack реализует "потоковый" десериализатор. Посмотрите на msgpack-c/example/c/lib_buffer_unpack.c
С уважением, NiteHawk
Хорошо, мне удалось это сделать.
Вот как написать:
#include <stdlib.h>
#include <msgpack.h>
#include <msgpack/fbuffer.h>
int main(int argc, char **argv) {
if(2 != argc) {
fprintf(stderr, "Call all writeFile <file>");
return;
}
FILE *fp = fopen(argv[1], "ab");
msgpack_packer pk;
msgpack_packer_init(&pk, fp, msgpack_fbuffer_write);
for(int i=0;i<2048;i++) {
msgpack_pack_int(&pk, i);
}
fclose(fp);
}
И вот как выглядит чтение:
#include <stdlib.h>
#include <msgpack.h>
static const int BUFFERSIZE = 2048;
int main(int argc, char **argv) {
if(2 != argc) {
fprintf(stderr, "Call with readFile <file>");
return 1;
}
char *inbuffer = (char *) malloc(BUFFERSIZE);
if(NULL == inbuffer) {
fprintf(stderr, "Out of memory!");
return 1;
}
FILE *fp = fopen(argv[1], "rb");
size_t off = 0;
size_t read = 0;
msgpack_unpacked unpacked;
msgpack_unpacked_init(&unpacked);
do {
read = fread(inbuffer, sizeof(char), BUFFERSIZE - off, fp);
off = 0;
while(msgpack_unpack_next(&unpacked, inbuffer, read, &off)) {
msgpack_object_print(stdout, unpacked.data);
puts("");
}
memcpy(inbuffer, &(inbuffer[off]), read-off);
off = read - off;
} while(read != 0);
free(inbuffer);
fclose(fp);
msgpack_unpacked_destroy(&unpacked);
return 0;
}
Я не пробовал, но думаю, что он будет работать и с более крупными объектами (массивами, картами и т. Д.).