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

时间:2016-03-01 00:36:39

标签: java zip protocol-buffers apache-kafka

我有kafka群集接收消息。 message是zip文件的字节数组。 zip文件包含二进制protobuf数据文件作为条目。我正在阅读zip文件并尝试反序列化protobuf条目,这就是我的代码遇到"protocol message has invalid UTF-8,invalid tag"例外的地方。

我可以在将二进制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();

二进制protobuf字节被gzip所以我需要gunzip

如果我使用gunzip,它不会以gzip格式抛出。

如果我跳过gunzip并执行parseFrom,我会收到无效的标记异常。

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

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文件,它工作!!!

我正在做zip / unzip错误的方式, 让我知道

1 个答案:

答案 0 :(得分:0)

这里有两个不同的东西:zip / unzip,以及处理protobuf。听起来这里的问题是第一个,它听起来像是破坏了protobuf数据。所以,现在:忘记protobuf ,只关注zip / unzip。记录原始消息的内容(在您压缩之前 - 可能是二进制文件或base-64块)。现在在接收端,在解压缩之后跟踪你获得的二进制(再次,二进制文件或base-64块)。如果他们并非完全100%相同,那么所有其他赌注都将关闭。在您成功复制原始二进制文件之前,protobuf没有机会。

如果这是问题:最好显示您的zip / unzip代码,以便我们看到它。

如果 正确地压缩/解压缩二进制文件,则问题将出现在你的protobuf代码中。

如果这是问题:显示序列化/反序列化代码会很好,所以我们可以看到它。