Как читать данные из файла AVRO, используя интерфейс C ++? - PullRequest
0 голосов
/ 02 мая 2019

Я пытаюсь написать простую программу для извлечения некоторых данных из набора файлов AVRO.Схема для каждого файла может быть разной, поэтому я хотел бы прочитать файлы в общем (т.е. без предварительной генерации и последующей компиляции в схеме для каждого) с использованием интерфейса C ++.

Я пытался следоватьgeneric.cc пример, но он предполагает отдельную схему, где я хотел бы прочитать схему из каждого файла AVRO.

Вот мой код:

#include <fstream>
#include <iostream>

#include "Compiler.hh"
#include "DataFile.hh"
#include "Decoder.hh"
#include "Generic.hh"
#include "Stream.hh"

const std::string BOLD("\033[1m");
const std::string ENDC("\033[0m");
const std::string RED("\033[31m");
const std::string YELLOW("\033[33m");

int main(int argc, char**argv)
{
    std::cout << "AVRO Test\n" << std::endl;

    if (argc < 2)
    {
        std::cerr << BOLD << RED << "ERROR: " << ENDC << "please provide an "
                  << "input file\n" << std::endl;
        return -1;
    }

    avro::DataFileReaderBase dataFile(argv[1]);
    auto dataSchema = dataFile.dataSchema();

    // Write out data schema in JSON for grins
    std::ofstream output("data_schema.json");
    dataSchema.toJson(output);
    output.close();

    avro::DecoderPtr decoder = avro::binaryDecoder();
    auto inStream = avro::fileInputStream(argv[1]);
    decoder->init(*inStream);

    avro::GenericDatum datum(dataSchema);
    avro::decode(*decoder, datum);
    std::cout << "Type: " << datum.type() << std::endl;

    return 0;
}

Каждый раз, когда я запускаю код, нетнезависимо от того, какой файл я использую, я получаю следующее:

$ ./avrotest twitter.avro
AVRO Test

прекращение вызова после создания экземпляра 'avro :: Exception'
what (): не может иметь отрицательную длину: -40 прервано

В дополнение к моим собственным файлам данных я попытался использовать файлы данных, расположенные здесь: https://github.com/miguno/avro-cli-examples, стот же результат.

Я попытался использовать утилиту avrocat для всех одинаковых файлов, и она работает нормально.Что я делаю не так?

(ПРИМЕЧАНИЕ: вывод схемы данных для каждого файла в JSON работает правильно, как и ожидалось)

1 Ответ

0 голосов
/ 02 мая 2019

После того, как куча еще дурачилась, я понял это. Вы должны использовать DataFileReader с шаблоном GenericDatum. Конечный результат выглядит примерно так:

#include <fstream>
#include <iostream>

#include "Compiler.hh"
#include "DataFile.hh"
#include "Decoder.hh"
#include "Generic.hh"
#include "Stream.hh"

const std::string BOLD("\033[1m");
const std::string ENDC("\033[0m");
const std::string RED("\033[31m");
const std::string YELLOW("\033[33m");

int main(int argc, char**argv)
{
    std::cout << "AVRO Test\n" << std::endl;

    if (argc < 2)
    {
        std::cerr << BOLD << RED << "ERROR: " << ENDC << "please provide an "
                  << "input file\n" << std::endl;
        return -1;
    }

    avro::DataFileReader<avro::GenericDatum> reader(argv[1]);
    auto dataSchema = reader.dataSchema();

    // Write out data schema in JSON for grins
    std::ofstream output("data_schema.json");
    dataSchema.toJson(output);
    output.close();

    avro::GenericDatum datum(dataSchema);
    while (reader.read(datum)) 
    {
        std::cout << "Type: " << datum.type() << std::endl;
        if (datum.type() == avro::AVRO_RECORD) 
        {
            const avro::GenericRecord& r = datum.value<avro::GenericRecord>();
            std::cout << "Field-count: " << r.fieldCount() << std::endl;

            // TODO: pull out each field
        }
    }

    return 0;
}

Возможно, такой пример следует включить в libavro ...

...