【问题标题】:Avro write and read works on one machine and not on otherAvro 读写在一台机器上工作,而不是在另一台机器上工作
【发布时间】:2015-07-23 18:10:03
【问题描述】:

这里有一些 Avro 代码在一台机器上运行但在另一台机器上失败并出现异常。

我们无法确定这里出了什么问题。

这是导致问题的代码。

Class<?> clazz = obj.getClass();
ReflectData rdata = ReflectData.AllowNull.get();
Schema schema = rdata.getSchema(clazz);

ByteArrayOutputStream os = new ByteArrayOutputStream();
Encoder encoder = EncoderFactory.get().binaryEncoder(os, null);
DatumWriter<T> writer = new ReflectDatumWriter<T>(schema, rdata);
writer.write(obj, encoder);
encoder.flush();
byte[] bytes = os.toByteArray();

String binaryString = new String (bytes, "ISO-8859-1");
BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(binaryString.getBytes("ISO-8859-1"), null);
GenericDatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord> (schema);
GenericRecord record = datumReader.read(null, decoder);

例外是:

org.apache.avro.AvroRuntimeException: Malformed data. Length is negative: -32
at org.apache.avro.io.BinaryDecoder.doReadBytes(BinaryDecoder.java:336)
at org.apache.avro.io.BinaryDecoder.readString(BinaryDecoder.java:263)
at org.apache.avro.io.ValidatingDecoder.readString(ValidatingDecoder.java:107)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:437)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:427)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:189)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:187)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:263)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:216)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:183)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:173)

【问题讨论】:

  • 请发布异常,包括其堆栈跟踪
  • @KristofferE,我添加了例外

标签: java encoding avro


【解决方案1】:

在 tomcat 参数中添加 Dfile.encoding=UTF-8 帮助我们解决了这个问题。

【讨论】:

  • 我会谨慎使用 ISO-8859-1。我相信 Avro 将字符串写为 UTF-8 字节,而 8859-1 与 UTF-8 不完全匹配。您可能会遇到破坏代码的字符,因为您在返回字节之前将字节解释为 8859-1,这可能会损坏数据。
  • ISO-8859-1 用于在以下代码中对无法通过 UTF-8 字节到字符串转换处理的数字进行二进制编码:new String (os.toByteArray(), "ISO- 8859-1");您是否发现此转换存在问题?
  • 我将不得不对 Avro 进行更多研究,以仔细检查它所使用的编码。如果不是 8859-1 就会有问题。你为什么首先将它转换为字符串?
  • Avro 的字符串是 UTF-8 字节。您可以在org.apache.avro.io.BinaryEncoder.writeString(String) 中看到这一点。我认为将 Avro 读取为 8859-1 字节是不对的。 Avro 是一种具有自己序列化的二进制格式(您可以在org.apache.avro.io.BinaryData 中看到它是如何编码的)。它使用 8859-1 的唯一时间是从 JSON 或 URL 读取。我强烈建议以字节为单位而不是创建中间字符串。如果您需要一个字符串进行调试,请将 Avro 记录转换为 JSON,或在您的 avsc 对象上使用 toString()(如果适用)。
猜你喜欢
  • 2017-08-07
  • 1970-01-01
  • 2014-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多