如何使用 C++ 接口从 AVRO 文件中读取数据?
How to read data from AVRO file using C++ interface?
我正在尝试编写一个简单的程序来从一堆 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("3[1m");
const std::string ENDC("3[0m");
const std::string RED("3[31m");
const std::string YELLOW("3[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
terminate called after throwing an instance of 'avro::Exception'
what(): Cannot have negative length: -40 Aborted
除了我自己的数据文件外,我还尝试使用位于此处的数据文件:https://github.com/miguno/avro-cli-examples,结果相同。
我尝试对所有相同的文件使用 avrocat
实用程序,它工作正常。我做错了什么?
(注意:输出 JSON 中每个文件的数据模式按预期正常工作)
经过一番折腾,我明白了。您应该使用 GenericDatum
模板化的 DataFileReader
。最终结果是这样的:
#include <fstream>
#include <iostream>
#include "Compiler.hh"
#include "DataFile.hh"
#include "Decoder.hh"
#include "Generic.hh"
#include "Stream.hh"
const std::string BOLD("3[1m");
const std::string ENDC("3[0m");
const std::string RED("3[31m");
const std::string YELLOW("3[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 中...
我正在尝试编写一个简单的程序来从一堆 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("3[1m");
const std::string ENDC("3[0m");
const std::string RED("3[31m");
const std::string YELLOW("3[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 Testterminate called after throwing an instance of 'avro::Exception'
what(): Cannot have negative length: -40 Aborted
除了我自己的数据文件外,我还尝试使用位于此处的数据文件:https://github.com/miguno/avro-cli-examples,结果相同。
我尝试对所有相同的文件使用 avrocat
实用程序,它工作正常。我做错了什么?
(注意:输出 JSON 中每个文件的数据模式按预期正常工作)
经过一番折腾,我明白了。您应该使用 GenericDatum
模板化的 DataFileReader
。最终结果是这样的:
#include <fstream>
#include <iostream>
#include "Compiler.hh"
#include "DataFile.hh"
#include "Decoder.hh"
#include "Generic.hh"
#include "Stream.hh"
const std::string BOLD("3[1m");
const std::string ENDC("3[0m");
const std::string RED("3[31m");
const std::string YELLOW("3[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 中...