如何使用apache avro GenericRecord获取动态数据?

use*_*610 5 c++ java avro

我想使用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();
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  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);
    
    Run Code Online (Sandbox Code Playgroud)

我发送theByteData到服务器,代码工作(没有例外),但结果是空的,谁能告诉我什么是错的?

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

小智 1

今天早上我遇到了同样的问题,我在 Avro Test Cpp 文件(“DataFileTests.cc”)中使用“testWriteGeneric”函数找到了解决方案。

例如:

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

{
  "type": "record",
  "name": "cpx",
  "fields" : [
  {"name": "re", "type": "double"},
  {"name": "im", "type" : "int"}
  ]
 }
Run Code Online (Sandbox Code Playgroud)

我的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();
}
Run Code Online (Sandbox Code Playgroud)