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

时间:2021-03-16 16:58:36

标签: java avro filereader

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

        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 问题 thisthis,但对我没有太大帮助。有人可以帮助我理解这一点。

2 个答案:

答案 0 :(得分:1)

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

大多数人对“avro 文件”的看法是一种格式,其中包含标题(其中包含编写器架构之类的内容),然后是实际数据:https://avro.apache.org/docs/current/spec.html#Object+Container+Files。 avro 文件的前四个字节应该是 b"Obj1" 或 0x4F626A01。您收到的错误是因为您尝试作为数据文件读取的二进制文件不是以标准魔术字节开头。

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

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

答案 1 :(得分:0)

您需要使用 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/

相关问题