如何使用Avro C++写入自定义编程定义Schema的文件?
使用自定义结构体写入Avro文件的解决方案
一、修复GenericDatum写入的编译错误
你碰到的编译错误是因为DataFileWriter<T>要求模板参数T必须有对应的avro::codec_traits特化,而avro::GenericDatum并不适配这个Writer类型。正确处理Generic模式数据的方式是使用avro::GenericDataFileWriter,修改后的代码如下:
#include <avro/Generic.h> #include <avro/DataFile.h> #include <avro/Compiler.h> #include <iostream> avro::ValidSchema SampleUserPhEntry() { avro::RecordSchema schema("UserEntries"); schema.addField("user_id", avro::LongSchema()); schema.addField("user_name", avro::StringSchema()); schema.addField("user_email", avro::StringSchema()); schema.addField("user_phone", avro::LongSchema()); return avro::ValidSchema(schema); } int WriteUserPhEntry() { avro::ValidSchema schema = SampleUserPhEntry(); avro::GenericDatum schema_datum(schema); const char* file_name = "user_entries.avro"; // 改用GenericDataFileWriter处理GenericDatum avro::GenericDataFileWriter writer(schema, file_name); avro::GenericRecord& record = schema_datum.value<avro::GenericRecord>(); record.field("user_id").value<int64_t>() = static_cast<int64_t>(64); record.field("user_name").value<std::string>() = "avro_user"; record.field("user_email").value<std::string>() = "avro_user@avro.com"; record.field("user_phone").value<int64_t>() = 1234567890; std::cout << record.field("user_id").value<int64_t>() << std::endl; writer.write(schema_datum); writer.close(); return 0; }
二、使用自定义结构体直接写入Avro文件
如果想直接用你定义的UserEntry结构体写入Avro文件,需要为该结构体特化avro::codec_traits模板,让Avro库知晓如何序列化结构体字段。注意:你的结构体字段user_phn和Schema中的user_phone名称不一致,需要先统一(下面示例中已将结构体字段改为user_phone)。
完整实现代码如下:
#include <avro/Generic.h> #include <avro/DataFile.h> #include <avro/Compiler.h> #include <iostream> #include <cstdint> // 统一结构体字段与Schema字段名称 struct UserEntry { int64_t user_id; std::string user_name; std::string user_email; int64_t user_phone; }; avro::ValidSchema SampleUserPhEntry() { avro::RecordSchema schema("UserEntries"); schema.addField("user_id", avro::LongSchema()); schema.addField("user_name", avro::StringSchema()); schema.addField("user_email", avro::StringSchema()); schema.addField("user_phone", avro::LongSchema()); return avro::ValidSchema(schema); } // 为UserEntry特化codec_traits模板 namespace avro { template<> struct codec_traits<UserEntry> { static void encode(Encoder& e, const UserEntry& u) { e.encodeLong(u.user_id); e.encodeString(u.user_name); e.encodeString(u.user_email); e.encodeLong(u.user_phone); } static void decode(Decoder& d, UserEntry& u) { d.decodeLong(u.user_id); d.decodeString(u.user_name); d.decodeString(u.user_email); d.decodeLong(u.user_phone); } }; } int WriteUserEntry() { avro::ValidSchema schema = SampleUserPhEntry(); const char* file_name = "user_entries_custom.avro"; // 直接使用DataFileWriter<UserEntry> avro::DataFileWriter<UserEntry> writer(file_name, schema); UserEntry entry; entry.user_id = 64; entry.user_name = "avro_user"; entry.user_email = "avro_user@avro.com"; entry.user_phone = 1234567890; writer.write(entry); writer.close(); std::cout << "自定义结构体写入完成" << std::endl; return 0; } int main() { WriteUserEntry(); return 0; }
关键说明
- 特化
codec_traits时,encode和decode的字段顺序必须和Schema中字段的定义顺序完全一致。 - 如果结构体字段和Schema字段名称不匹配,只要序列化/反序列化的顺序对应也能工作,但建议保持名称一致以提高可读性和可维护性。
内容的提问来源于stack exchange,提问作者0Nicholas
相关产品推荐
相关产品推荐

