Java 无法反序列化压缩的协议缓冲区
我让卡夫卡集群接收消息。消息是zip文件的字节数组。zip文件包含二进制protobuf数据文件作为条目。我正在读取zip文件并尝试反序列化protobuf条目,这就是我的代码遇到的Java 无法反序列化压缩的协议缓冲区,java,zip,protocol-buffers,apache-kafka,Java,Zip,Protocol Buffers,Apache Kafka,我让卡夫卡集群接收消息。消息是zip文件的字节数组。zip文件包含二进制protobuf数据文件作为条目。我正在读取zip文件并尝试反序列化protobuf条目,这就是我的代码遇到的“协议消息具有无效的UTF-8,无效的标记”异常的地方 GZIPInputStream gzip = new GZIPInputStream( new ByteArrayInputStream(baos.toByteArray()));
“协议消息具有无效的UTF-8,无效的标记”
异常的地方
GZIPInputStream gzip = new GZIPInputStream(
new ByteArrayInputStream(baos.toByteArray()));
MyProtoObject mpo = null;
try {
mpo = MyProtoObject.parseFrom(protoBytes);
} catch (InvalidProtocolBufferException e1) {
e1.printStackTrace();
}
} catch (IOException e1) {
e1.printStackTrace();
}
在将二进制protobuf文件作为压缩字节数组发送到代理之前,我能够对其进行反序列化
但是,当我压缩这些二进制protobuf文件,向kafka生成消息,使用它,然后尝试反序列化zip流中的条目时,我面临着一些问题
我不知道谁是罪魁祸首
因为这些二进制协议缓冲区是gzip压缩的,所以再次压缩它们会把事情搞砸吗
有人能给我们点启示吗
谢谢
**************编辑**************
Producer Side:
public byte[] getZipfileBytes() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(baos);
CheckedOutputStream checkSum = new CheckedOutputStream(zipOut, new Adler32());
try {
ZipEntry zipEntry = new ZipEntry(testFile.getName());
byte[] protoBytes = IOUtils.toByteArray(new FileInputStream(testFile));
System.out.println("bytes length:\t"+protoBytes.length);
zipEntry.setSize(protoBytes.length);
zipOut.putNextEntry(zipEntry);
zipOut.write(protoBytes);
zipOut.close();
System.out.println("checksum:"+checkSum.getChecksum().getValue());
zipBytes = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return zipBytes;
}
Consumer Side:
processConsumerRecord(ConsumerRecord<String, byte[]> record) {
String key = record.key();
byte[] dataPacket = record.value();
ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(dataPacket));
CheckedInputStream checkSum = new CheckedInputStream(zipIn,
new Adler32());
ZipEntry zipEntry;
try {
zipEntry = zipIn.getNextEntry();
while (zipEntry != null) {
String name = zipEntry.getName();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
IOUtils.copy(zipIn, baos);
byte[] protoBytes = baos.toByteArray();
checkSum.getChecksum().getValue()在生成和使用zip字节数组时返回1以下是调试期间zipEntry变量的值:
producer
zipEntry ZipEntry (id=44)
comment null
crc 2147247736
csize 86794
extra null
flag 2056
method 8
name "test.dat" (id=49)
size 92931
time 1214084891
consumer
zipEntry ZipEntry (id=34)
comment null
crc 2147247736
csize 86794
extra null
flag 0
method 8
name "test.dat" (id=39)
size 92931
time 1214084891
我甚至测试了另一种方法,不是在内存中处理protobytes,而是将zip文件写入磁盘,通过winzip手动解压缩,然后反序列化解压缩的二进制proto文件,它工作了
我是不是拉错了,
让我知道这里有两件不同的事情:压缩/解压缩和处理protobuf。听起来这里的问题是第一个问题,听起来好像是破坏了protobuf数据。所以,现在:忘掉protobuf,只专注于压缩/解压。记录原始消息的内容(在压缩之前-可能是二进制文件或base-64块)。现在,在接收端,在解压后(同样是二进制文件或base-64块),跟踪二进制文件中的。如果它们不是绝对100%相同,则所有其他赌注都将被取消。在成功复制原始二进制文件之前,protobuf是不可能的 如果这是一个问题:最好显示您的邮政编码,这样我们就可以看到它 如果您正确地压缩/解压缩了二进制文件,那么问题就出在protobuf代码中
如果这是一个问题:最好显示您的序列化/反序列化代码,这样我们就可以看到它。这里有两个不同的功能:zip/unzip和处理protobuf。听起来这里的问题是第一个问题,听起来好像是破坏了protobuf数据。所以,现在:忘掉protobuf,只专注于压缩/解压。记录原始消息的内容(在压缩之前-可能是二进制文件或base-64块)。现在,在接收端,在解压后(同样是二进制文件或base-64块),跟踪二进制文件中的。如果它们不是绝对100%相同,则所有其他赌注都将被取消。在成功复制原始二进制文件之前,protobuf是不可能的 如果这是一个问题:最好显示您的邮政编码,这样我们就可以看到它 如果您正确地压缩/解压缩了二进制文件,那么问题就出在protobuf代码中
如果这是问题:最好显示您的序列化/反序列化代码,以便我们可以看到它。小/大端转换(或缺少)可能会导致问题吗?@Emil您选择的protobuf库应该在内部处理端转换;protobuf规范明确了这些细节,如果任何一个已建立的库出错,我都会感到惊讶。您的zip/unzip代码不应该关心endianness——它只需要在进程的开始和结束时以相同的顺序获得相同的字节。我完全同意。正如您所说,我认为忽略protobuf步骤并确保zip/unzip步骤按预期工作是一个好主意。只是说持久性会在传输时引起问题data@MarcGravell,添加了代码片段和更多信息。我在发送之前和接收之后验证了二进制原始字节,它们是相同的。假设我已经用正确的方式做了。请告诉我您的查找扫描小/大端号转换(或缺少转换)可能导致问题?@Emil您选择的protobuf库应该在内部处理端号转换;protobuf规范明确了这些细节,如果任何一个已建立的库出错,我都会感到惊讶。您的zip/unzip代码不应该关心endianness——它只需要在进程的开始和结束时以相同的顺序获得相同的字节。我完全同意。正如您所说,我认为忽略protobuf步骤并确保zip/unzip步骤按预期工作是一个好主意。只是说持久性会在传输时引起问题data@MarcGravell,添加了代码片段和更多信息。我在发送之前和接收之后验证了二进制原始字节,它们是相同的。假设我已经用正确的方式做了。请告诉我你的发现