You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:47:31