【问题标题】:How to use apache avro GenericRecord for dynamic data?如何将 apache avro GenericRecord 用于动态数据?
【发布时间】:2012-11-18 14:29:16
【问题描述】:

我想使用 Apache Avro 来序列化我的数据,我的客户端是用 C++ 编写的,而我的服务器是用 Java 编写的。

  1. 我的服务器 java 代码如下所示:

    Schema scm = new Schema.Parser().parse("....shcema String.....");
    ByteArrayInputStream inputStream = new ByteArrayInputStream(record.array());
    Decoder coder = new DecoderFactory().directBinaryDecoder(inputStream, null);
    GenericDatumReader<GenericRecord> reDatumReader = new GenericDatumReader<GenericRecord>(scm);
    try {
        GenericRecord result = (GenericRecord)reDatumReader.read(null, coder);
                //here! the result "name", "num_groups" is empty!
        System.out.println(result.get("name")+"   "+result.get("num_groups"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    
  2. 还有我的客户代码:

    std::string schemaDescript ="....shcema String.....";
    
    std::stringstream rsStream(schemaDescript);
    avro::ValidSchema rSchema;
    avro::compileJsonSchema(rsStream, rSchema);
    avro::EncoderPtr encoder = avro::binaryEncoder();
    std::auto_ptr<avro::OutputStream> oStream = avro::memoryOutputStream();
    encoder->init(*oStream);   
    avro::GenericDatum rData(rSchema);
    avro::GenericRecord sReord = rData.value<avro::GenericRecord>();
    sReord.setFieldAt(0, avro::GenericDatum("i am nice"));
    sReord.setFieldAt(1, avro::GenericDatum(1));
    sReord.setFieldAt(2, avro::GenericDatum(12));
    sReord.setFieldAt(3, avro::GenericDatum(13));
    
    avro::GenericWriter gwriter(rSchema, encoder);
    gwriter.write(rData);
    oStream->flush();
    
    std::auto_ptr<avro::InputStream> inSt = avro::memoryInputStream(*oStream);
    avro::StreamReader instReader(*inSt);
    
    size_t outputLen = oStream->byteCount();
    uint8_t* theByteData = new uint8_t[outputLen];
    instReader.hasMore();
    instReader.readBytes(theByteData, outputLen);
    

我将theByteData 发送到服务器,代码有效(无异常),但结果为空,谁能告诉我有什么问题?

以及为什么在 Java 中我们通过键获得价值:result.get("name");但在 C++ 中,我们通过索引获得价值:record.fieldAt(0).value&lt;string&gt;()。如果我无法使用字符串键获取值,如何将索引与字符串键匹配?

【问题讨论】:

  • 感谢 dominikh,编辑了我的问题。
  • 3 年后,有什么消息吗?

标签: java c++ avro


【解决方案1】:

今天早上我遇到了同样的问题,我在 Avro 测试 Cpp 文件(“DataFileTests.cc”)中找到了一个解决方案,其中包含“testWriteGeneric”函数。

例如:

我的架构文件(cpx.json):

{
  "type": "record",
  "name": "cpx",
  "fields" : [
  {"name": "re", "type": "double"},
  {"name": "im", "type" : "int"}
  ]
 }

我的 Cpp 文件:

typedef std::pair<avro::ValidSchema, avro::GenericDatum> Pair;

int main(int ac, char **av)
{

    // encode
    std::ifstream ifs(cpx.json);
    avro::ValidSchema schema;
    avro::compileJsonSchema(ifs, schema);

    // I create a pair of validSchema and GenericDatum
    Pair p(schema, avro::GenericDatum());

    avro::GenericDatum &Data = p.second;
    Data = avro::GenericDatum(schema);
    avro::GenericRecord &sReord = Data.value<avro::GenericRecord>();

    // I set my values
    sReord.setFieldAt(sReord.fieldIndex("re"), avro::GenericDatum(42.5));
    sReord.setFieldAt(sReord.fieldIndex("im"), avro::GenericDatum(24));


    // I create a DataFileWriter and i write my pair of ValidSchema and GenericValue
    avro::DataFileWriter<Pair> dataFileWriter("test.bin", schema);
    dataFileWriter.write(p);
    dataFileWriter.close();
}

【讨论】:

    【解决方案2】:

    以下语句中客户端代码有2个问题

    avro::GenericRecord sReord = rData.value<avro::GenericRecord>();
    sReord.setFieldAt(0, avro::GenericDatum("i am nice"));
    

    第二条语句将导致调用 avro::GenericDatum(bool) 而不是预期的 GenericDatum(const std::string&amp;)。 因此,字符串字段保持为空,因此当您尝试读取它时,将返回空字符串。所以,用下面的语句替换上面的语句应该可以工作

    std::string s("i am nice");
    sReord.setFieldAt(0, avro::GenericDatum(s));
    

    在第一个语句中,sRecord 应该被声明为引用,因为这就是 rData.value() 返回的内容。不作为参考只是将其替换为新副本,因此写入其中的任何值实际上都不会写入基础流中。所以,应该是

    avro::GenericRecord& sReord = rData.value<avro::GenericRecord>();
    

    另外,你不需要 GenericWriter 并且可以使用 Encoder 对象本身来编写

    avro::encode(*encoder, rData);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      • 2020-03-17
      • 1970-01-01
      • 2019-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多