我有一个用List<TestAvroModel>
序列化的ByteArrayInputStream
,它是SpecificRecord的实现。我找不到让 Avro 了解序列化列表的方法,所以我做了一个黑客的方式来循环ByteArrayInputStream
.
//TestAvroModel is an implementation of SpecificRecord
List<TestAvroModel> models;
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
for(TestAvroModel model: models) {
DatumWriter<SpecificRecord> writer = new SpecificDatumWriter<>(model.getSchema());
Encoder encoder = new EncoderFactory().binaryEncoder(byteArrayStream, null);
writer.write(model, encoder);
encoder.flush();
}
//This was pre-serialized with a List of TestAvroModel
ByteArrayInputStream inputStream;
DatumReader<TestAvroModel> reader = new SpecificDatumReader<>(TestAvroModel.getClassSchema());
Decoder decoder = DecoderFactory().get().binaryDecoder(inputStream, null);
List<TestAvroModel> records = new ArrayList<>();
boolean eof = false;
while(!eof) {
try {
records.add(reader.read(null, decoder));
catch(EOFException ex) {
eof = true;
}
}
这种方式工作并一次读取一个序列化List<TestAvroModel>
并将其添加到我的记录列表中。虽然循环DatumReader
直到EOFException
似乎不是最好的方法,但我还没有找到更好的方法。
我在 Avro图书馆中找不到任何处理包含多个 Avro 记录的InputStream
的东西。尽管它必须在流中具有断点,以便 Avro 能够像我上面所做的那样读取单个记录。重申一下,有没有人知道比上面显示的更好的方法来循环DatumReader
?
Decoder
似乎为此目的定义了isEnd(): Boolean
:
如果当前二进制解码器位于其源的末尾,则返回 true 数据,并且无法在不抛出 EOFException 的情况下进一步读取或 其他 IOException。
这应该有效:
...
while(!decoder.isEnd()) {
records.add(reader.read(null, decoder));
}