2012-11-18 4 views
5

Apache Avroを使用してデータをシリアル化したい、クライアントがC++で書かれていて、サーバーがJavaで書かれています。動的データにapache avro GenericRecordを使用するには?

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(); 
} 
  • そして、私のクライアントコード:

    1. 私のサーバーのJavaコードは次のようになり、私は、サーバーにtheByteData送信

      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); 
      

    、コードが動作します(例外はありません)、結果は空ですが、何が間違っているか教えてください。

    なぜJavaでは、キーで値が得られるのですか:result.get("name");しかし、C++ではインデックス:record.fieldAt(0).value<string>()で値を取得します。文字列キーで値を取得できない場合、その文字列キーにインデックスを一致させる方法は?

  • +0

    としてエンコーダーオブジェクト自体を使用して書くことができます

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

    でなければなりませんdominikhのおかげで、私の質問を編集しました。 – user1833610

    +0

    3年後、ニュースはありますか? –

    答えて

    1

    私は今朝も同じ問題を抱えていました。私は、「testWriteGeneric」機能を備えたAvro Test Cppファイル( "DataFileTests.cc")の解決策を見つけました。例えば

    私のスキーマファイル(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(); 
    } 
    
    0

    次のクライアントコードと2つの問題があります。

    2番目のステートメントはavro::GenericDatum(bool)を呼び出し、GenericDatum(const std::string&)は意図していません。 これにより、文字列フィールドは空のままなので、読み込もうとすると空の文字列が返されます。それはrData.value(によって返されるものだように、最初の文では

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

    を動作するはずです以下での文の上に置き換え、sRecord)を基準として宣言する必要があります。参照として取っておかないと、新しいコピーで置き換えられるだけで、そこに書き込まれた値は実際には基本ストリームに書き込まれません。だから、それはまた、あなたがGenericWriterを必要としないと

    avro::encode(*encoder, rData); 
    
    関連する問題