Swift和Go之间的Zlib压缩

My Swift application communicates to a server written in Go. I'd like the data transferred to be compressed using Zlib, but it appears that the compression results are different from Swift and Go.

Here is the Go version:

sourceString := "A-t-elle besoin d'autres preuves ? Acceptez-la pour le plaisir. J'ai tant fait que de la cueillir, Et c'est presque une fleur-des-veuves."

// Compression
var b bytes.Buffer
writer := zlib.NewWriter(&b)
writer.Write([]byte(sourceString))
writer.Close()

// Base 64
b64 := base64.StdEncoding.EncodeToString(b.Bytes())

fmt.Println(b64)

It gives the following (Go Playground):

eJwczb2tg0AQReFWbkbylhaeCJy4i/FykUYaLev5IXD1Fs6Pzre1bDQjXoxTB/ZFKp2B6ayLgX9svXMmP80E8yyHEdNEQ33FcxFFykgcool3ETthgl5UM/U/PBJ9YeS9jDuoQRzG8rYz2vVz1m8AAAD//++yMFQ=

Now using the following Swift code (based on this article):

let sourceString = "A-t-elle besoin d'autres preuves ? Acceptez-la pour le plaisir. J'ai tant fait que de la cueillir, Et c'est presque une fleur-des-veuves."

var sourceBuffer = Array(sourceString.utf8)

let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: sourceString.count)

let algorithm = COMPRESSION_ZLIB

let compressedSize = compression_encode_buffer(destinationBuffer, sourceString.count, &sourceBuffer, sourceString.count, nil, algorithm)

if compressedSize == 0 {
    fatalError("Encoding failed.")
}

// EDIT after @Steffen Ullrich answer
// let encodedString = String(cString: destinationBuffer)
// let encodedStringb64 = Data(encodedString.utf8).base64EncodedString()

let encodedData = NSData(bytesNoCopy: destinationBuffer, length: compressedSize)
let encodedStringb64 = encodedData.base64EncodedString()

print(encodedStringb64)

We get:

H̶e̶+̶/̶v̶T̶E̶O̶7̶7̶+̶9̶M̶A̶x̶D̶0̶a̶t̶w̶7̶7̶+̶9̶U̶u̶+̶/̶v̶Q̶p̶F̶7̶7̶+̶9̶L̶O̶+̶/̶v̶e̶+̶/̶v̶e̶+̶/̶v̶T̶D̶v̶v̶7̶0̶=̶ Hc0xDsMwDEPRq3DzUucKRYYsvYXqMIAAwXFtKUNPX6cTlwf+NXumGfHmOLViTxLeOdA645r7xFoKm/ObTdDO6Ji6mejQvuCVROFSHYeo4xPETkxZgmqm/YHNURKH35fjBlGJwxg97xz5+neWHw==

As you can see it is very different, what am i doing wrong here?

1个回答



我不熟悉Swift,但是Go代码返回了zlib(RFC 1950)压缩字符串,而根据Apple的文档 Swift代码最多应返回一个deflate压缩字符串(RFC 1951),即类似于zlib压缩但没有2字节zlib标头的字符串。 </ p>

有了这些知识,可以正确解压缩从Go代码返回的字符串,而不能从Swift返回的字符串解压缩。 大小上的差异也很明显,这让我假设某些东西被切断了。 看起来您将压缩数据 destinationBuffer </ code>视为 cString </ code>,这意味着字符串内的任何 \ 0 </ code>字节都将被视为 字符串的结尾。 压缩结果可能会存在这样的 \ 0 </ code>字节,并且该字符串在此处被截断,即您的输出仅显示实际 destinationBuffer </ code>的一部分。 (编辑:由于OP更改了问题并获得了正确的结果,因此最后一部分不再适用)。</ p>
</ div>

展开原文

原文

I'm not familiar with Swift but the Go code returns a zlib (RFC 1950) compressed string while according to the documentation from Apple the Swift code should at most return a deflate compressed string (RFC 1951), i.e. like the zlib compressed but without the 2 byte zlib header.

With that knowledge the string returned from the Go code can be properly decompressed while the string returned from Swift can not. The difference in size is also obvious which lets me assume that something was cut off. It looks like you treat the compressed data destinationBuffer as a cString, which means that any \0-byte inside the string will be treated as the end of the string. It is likely that such \0 byte exists as the result of compression and that the string got cut off there, i.e. that your output shows only part of the real destinationBuffer. (EDIT: the last part does not apply anymore since the OP changed the question with a proper result).

douzha5990
douzha5990 是的,我编辑了问题以输出适当的base64字符串(之后我尝试对其进行解压缩,并且它可以工作)。
一年多之前 回复
duangai2831
duangai2831 RFC 1950/1951的区别只是一个问题。 另一个是您从Swift获得的结果不正确,即无法再次将其解压缩。
一年多之前 回复
doudu7626
doudu7626 RFC 1950 / RFC 1951的不同之处在于问题,谢谢! 我通过删除前2个字节成功地使用Swift将Go输出解压缩了:encodeStr?.subdata(in:2 .. <encodeStrLen)(with让encodeStr = Data(base64Encoded:b64SourceStr))。 很少有人遇到这个问题,但是我之前没有看到他们的答案...:/
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐