Java 无法反序列化压缩的协议缓冲区

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()));

我让卡夫卡集群接收消息。消息是zip文件的字节数组。zip文件包含二进制protobuf数据文件作为条目。我正在读取zip文件并尝试反序列化protobuf条目,这就是我的代码遇到的
“协议消息具有无效的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,添加了代码片段和更多信息。我在发送之前和接收之后验证了二进制原始字节,它们是相同的。假设我已经用正确的方式做了。请告诉我你的发现