如何使用 C++ 接口从 AVRO 文件读取数据?

2023-12-01

我正在尝试编写一个简单的程序来从一堆 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测试

抛出“avro::Exception”实例后调用终止
What():不能有负长度:-40 已中止

除了我自己的数据文件之外,我还尝试使用位于此处的数据文件:https://github.com/miguno/avro-cli-examples,结果相同。

我尝试使用avrocat实用程序适用于所有相同的文件,并且工作正常。我究竟做错了什么?

(注意:以 JSON 格式输出每个文件的数据模式可以正常工作)


经过一番折腾,我终于明白了。你应该使用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 中......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 C++ 接口从 AVRO 文件读取数据? 的相关文章

随机推荐