java.io.IOException: 从文件读取 Avro 时不是数据文件
java.io.IOException: Not a data file while reading Avro from file
以下代码用于序列化数据。
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)
这里发生了什么问题。我提到了另外两个类似的 Whosebug 问题 and ,但对我帮助不大。谁能帮我理解一下。
您需要利用 Avro 来写入和读取数据,否则不会写入架构(因此会出现“不是数据文件”消息)。 (参见:https://cwiki.apache.org/confluence/display/AVRO/FAQ#FAQ-HowcanIserializedirectlyto/fromabytearray?)
如果您只是想序列化对象,请参阅:https://mkyong.com/java/how-to-read-and-write-java-object-to-a-file/
实际数据以 Avro 二进制格式编码,但通常传递的不仅仅是编码数据。
大多数人认为的“avro 文件”是一种格式,其中包括 header(具有编写器架构之类的内容),然后是实际数据:https://avro.apache.org/docs/current/spec.html#Object+Container+Files。 avro 文件的前四个字节应该是 b"Obj1" 或 0x4F626A01。您收到的错误是因为您尝试作为数据文件读取的二进制文件不是以标准魔术字节开头。
另一种标准格式是单一 object 编码:https://avro.apache.org/docs/current/spec.html#single_object_encoding。这种二进制格式应该以0xC301开头。
但如果我不得不猜测,您拥有的二进制文件可能只是原始序列化数据,没有任何类型的 header 信息。尽管在不知道您拥有的字节数组是如何创建的情况下很难确定。
以下代码用于序列化数据。
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)
这里发生了什么问题。我提到了另外两个类似的 Whosebug 问题
您需要利用 Avro 来写入和读取数据,否则不会写入架构(因此会出现“不是数据文件”消息)。 (参见:https://cwiki.apache.org/confluence/display/AVRO/FAQ#FAQ-HowcanIserializedirectlyto/fromabytearray?)
如果您只是想序列化对象,请参阅:https://mkyong.com/java/how-to-read-and-write-java-object-to-a-file/
实际数据以 Avro 二进制格式编码,但通常传递的不仅仅是编码数据。
大多数人认为的“avro 文件”是一种格式,其中包括 header(具有编写器架构之类的内容),然后是实际数据:https://avro.apache.org/docs/current/spec.html#Object+Container+Files。 avro 文件的前四个字节应该是 b"Obj1" 或 0x4F626A01。您收到的错误是因为您尝试作为数据文件读取的二进制文件不是以标准魔术字节开头。
另一种标准格式是单一 object 编码:https://avro.apache.org/docs/current/spec.html#single_object_encoding。这种二进制格式应该以0xC301开头。
但如果我不得不猜测,您拥有的二进制文件可能只是原始序列化数据,没有任何类型的 header 信息。尽管在不知道您拥有的字节数组是如何创建的情况下很难确定。