java.io.IOException:从文件中读取Avro时不是数据文件



以下代码用于序列化数据。

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
BinaryEncoder binaryEncoder =
EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(data.getSchema());
datumWriter.setSchema(data.getSchema());
datumWriter.write(data, binaryEncoder);
binaryEncoder.flush();
byteArrayOutputStream.close();
result = byteArrayOutputStream.toByteArray();

我使用了以下命令

FileUtils.writeByteArrayToFile(new File("D:/sample.avro"), data);

将avro字节数组写入文件。但当我尝试使用读取相同内容时

File file = new File("D:/sample.avro");
try {
dataFileReader = new DataFileReader(file, datumReader);
} catch (IOException exp) {
System.out.println(exp);
System.exit(1);
}

它抛出异常

java.io.IOException: Not a data file.
at org.apache.avro.file.DataFileStream.initialize(DataFileStream.java:105)
at org.apache.avro.file.DataFileReader.<init>(DataFileReader.java:97)
at org.apache.avro.file.DataFileReader.<init>(DataFileReader.java:89)

这里出了什么问题。我参考了另外两个类似的stackoverflow问题this和this,但对我没有太大帮助。有人能帮我理解吗。

实际数据以Avro二进制格式编码,但通常传递的不仅仅是编码数据。

大多数人认为;avro文件";是一种包括标头(具有类似于编写器模式的内容(和实际数据的格式:https://avro.apache.org/docs/current/spec.html#Object+容器+文件。avro文件的前四个字节应该是b〃;Obj1";或0x4F626A01。你得到的错误是因为你试图作为数据文件读取的二进制文件不是以标准的魔术字节开始的。

另一种标准格式是单对象编码:https://avro.apache.org/docs/current/spec.html#single_object_encoding.这种类型的二进制格式应该以0xC301开头。

但是,如果我不得不猜测的话,你所拥有的二进制文件可能只是没有任何头部信息的原始序列化数据。尽管如果不知道字节数组是如何创建的,很难确定。

您需要使用Avro来写入和读取数据,否则就不会写入模式(因此会出现"不是数据文件"消息(。(请参见:https://cwiki.apache.org/confluence/display/AVRO/FAQ#FAQ-如何直接串行传输到/从数据线?(

如果您只是想序列化一个对象,请参阅:https://mkyong.com/java/how-to-read-and-write-java-object-to-a-file/

最新更新