Java 与iOS和Android上的zlib通缩结果不同。如何获得相同的结果?

Java 与iOS和Android上的zlib通缩结果不同。如何获得相同的结果?,java,android,ios,zlib,deflate,Java,Android,Ios,Zlib,Deflate,目前,在我的iOS应用程序中,我正在使用zlib对数据进行泄密,我希望在Android中实现相同的逻辑,以便在这两个平台中处理的泄密数据兼容并可以传输 在下面的代码中,inputString都是任意随机字符串,如: 开发人员信任堆栈溢出来帮助解决编码问题,并使用堆栈溢出来寻找工作机会。我们致力于让互联网成为一个更好的地方,我们的产品旨在丰富开发者的生活,让他们在职业生涯中成长和成熟 在iOS中,使用以下代码段: NSData *rawData = [inputString dataUsingEn

目前,在我的iOS应用程序中,我正在使用
zlib
对数据进行泄密,我希望在Android中实现相同的逻辑,以便在这两个平台中处理的泄密数据兼容并可以传输

在下面的代码中,
inputString
都是任意随机字符串,如:

开发人员信任堆栈溢出来帮助解决编码问题,并使用堆栈溢出来寻找工作机会。我们致力于让互联网成为一个更好的地方,我们的产品旨在丰富开发者的生活,让他们在职业生涯中成长和成熟

在iOS中,使用以下代码段:

NSData *rawData = [inputString dataUsingEncoding:NSUTF8StringEncoding];
NSInputStream * src = [NSInputStream inputStreamWithData:rawData];
[src open];
NSOutputStream * dest = [NSOutputStream outputStreamToMemory];
[dest open];
int res = [self deflateDataStream:src toOutputStream:dest level:Z_DEFAULT_COMPRESSION];
[dest close];
[src close];

if (res != Z_OK) return nil;

NSData *ret = [dest propertyForKey:NSStreamDataWrittenToMemoryStreamKey];

+ (int) deflateDataStream:(NSInputStream *)source toOutputStream:(NSOutputStream *)dest level:(int)level {
    int ret, flush;
    unsigned have;
    z_stream strm;
    unsigned char inBuf[CHUNK];
    unsigned char outBuf[CHUNK];

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    ret = deflateInit2(&strm, level, Z_DEFLATED, (16+MAX_WBITS), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
    if (ret != Z_OK) return ret;

    do {
        NSInteger res = [source read:inBuf maxLength:CHUNK];
        if (res < 0)  {
            NSLog(@"!!! Error reading stream: %ld %@", (long)source.streamStatus, source.streamError);
            (void)deflateEnd(&strm);
            return Z_ERRNO;
        }

        flush = [source hasBytesAvailable] ? Z_NO_FLUSH : Z_FINISH;
        strm.avail_in = (uInt)res;
        strm.next_in = inBuf;

        do {
            strm.avail_out = CHUNK;
            strm.next_out = outBuf;
            ret = deflate(&strm, flush);
            assert(ret != Z_STREAM_ERROR);
            have = CHUNK - strm.avail_out;

            res = [dest write:outBuf maxLength:have];
            if (res != have || res < 0) {
                (void)deflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);
        assert(strm.avail_in == 0);
    } while (flush != Z_FINISH);
    assert(ret == Z_STREAM_END);

    (void)deflateEnd(&strm);
    return Z_OK;
}
然而,上面在Android上的实现返回的结果与在iOS上的结果不同,这使得我现有的iOS应用程序无法使用它

使用我引用的测试字符串,iOS产生197字节大小的
NSData
,其中原始字符串数据为273字节。虽然Android上的原始输入也是273字节大小,但上面的实现给出的结果是185字节

改变iOS端的逻辑目前是不可行的,因为这将涉及许多额外的过程,如提交审查等

我假设两个平台中的底层算法应该是相同的?如果是这种情况,为什么结果不同?我做错什么了吗?我怎样才能纠正它并在Android上获得同样的结果


谢谢

您使用的是不同的级别,在iOS上使用的是
MAX\u MEM\u LEVEL
(9),而在Android上使用的是
DEFAULT\u COMPRESSION
(-1)。在Android上尝试使用
BEST\u COMPRESSION
(9)

deflateInit2()
中的
16+MAX\WBITS
正在请求gzip格式,而
Deflater
类正在请求zlib格式。您可以去掉iOS代码中的
16+
,以请求zlib格式


请注意,输出可能仍然不同,因为对于相同的输入,不要求来自不同压缩器的压缩数据相同。重要的是,你从解压器中得到的东西与你送给任何一台压缩机的一样。

iOS中有两种放气方法:

1. deflateInit(strm, level)
2. deflateInit2(strm, level, method, windowBits, memLevel, strategy)
第一个与java的deflater兼容。还要确保在iOS和Java(Android)中使用相同的压缩级别

压缩级别:

   -1: default
    0: NO_COMPRESSION
    1: BEST_SPEED //generally used 
       ......
    9: BEST_COMPRESSION
   -1: default
    0: NO_COMPRESSION
    1: BEST_SPEED //generally used 
       ......
    9: BEST_COMPRESSION