我有 2 个用 C# 和 Scala 编写的 deflate 函数,当使用相同的输入运行时,返回的字节数组在前导字节和尾随字节中存在差异(中间字节之间的差异是由无符号/有符号字节机制预期的) C# 和 Scala)。
\nScala 中的 Deflate 函数:
\nimport java.io.ByteArrayOutputStream\nimport java.util.zip.{Deflater, DeflaterOutputStream}\n\nimport zio._\n\n\nobject ZDeflater {\n val deflater = ZManaged.makeEffectTotal(new Deflater(Deflater.DEFLATED, true))(_.end)\n\n val buffer = ZManaged.fromAutoCloseable(ZIO.succeed(new ByteArrayOutputStream()))\n\n val stream = for {\n d <- deflater\n b <- buffer\n s <- ZManaged.fromAutoCloseable(ZIO.succeed(new DeflaterOutputStream(b, d, true)))\n } yield (b, s)\n\n def deflate(input: Array[Byte]): RIO[blocking.Blocking, Array[Byte]] = stream.use { case (buffer, stream) =>\n for {\n () <- blocking.effectBlocking(stream.write(input))\n () <- blocking.effectBlocking(stream.flush())\n result = buffer.toByteArray\n } yield result\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nC# 中的放气函数:
\nprivate static byte[] Deflate(byte[] uncompressedBytes)\n{\n using (var output = new MemoryStream())\n {\n using (var zip = new DeflateStream(output, CompressionMode.Compress, true))\n {\n zip.Write(uncompressedBytes, 0, uncompressedBytes.Length);\n }\n\n return output.ToArray();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n放气后的输出:\nScala:
\nZDeflater.deflate(data.getBytes(StandardCharsets.UTF_8))\n\n124, -111, \xe2\x80\xa6, 126, 1, 0, 0, -1, -1\nRun Code Online (Sandbox Code Playgroud)\nC#:
\nDeflate(Encoding.UTF8.GetBytes(data))\n125, 145, \xe2\x80\xa6, 126, 1\nRun Code Online (Sandbox Code Playgroud)\n有谁知道是什么原因导致第一个和最后一个字节之间的差异?你的任何假设对我都非常有帮助。谢谢一堆
\nP/s:我们遇到了一个问题,C# 的 Deflate 输出适用于特定的第三部分,而 Scala 的输出则不然。所以我想弄清楚如何使 Scala 的输出与 C# 的输出相同
\n如此处所述,Java 的Deflater类将字节序列压缩为ZLIB 压缩数据格式。ZLIB 数据格式以DEFLATE 数据格式包装压缩数据,并在压缩数据后带有标头和 ADLER-32 校验和。
Microsoft 的DeflateStream文档对于确切的数据格式不准确。但它实际上以原始 DEFLATE 数据格式而不是 ZLIB 格式(dotnet-2236)生成数据。有了它,它的输出也与 HTTP 的“deflate”传输编码不兼容,后者实际上引用了 ZLIB 数据格式而不是 DEFLATE 数据格式(RFC-2616)。
但是现在如何使用 Scala 和 C# 获得相同的输出呢?
A) 使用 Scala 也以原始 DEFLATE 格式写入数据
该类Deflater有一个带有参数的重载构造nowrap函数,允许省略标头和校验和。将此参数设置为true将产生原始 DEFLATE 数据格式的压缩数据。如果您还计划在 Java 中反序列化数据,请Inflater仔细阅读构造函数的 Javadoc。
B) 使用 C# 也以 ZLIB 格式写入数据(推荐)
使用 .NET 的ZLibStream类或任何第三方库代替该类Deflater,以 ZLIB 格式序列化数据。
C) 使用 GZIP 格式代替
GZIP 格式与 ZLIB 相当,但使用不同的标头和不同的校验和。.NET 和 Java 都为其提供了显式流类。尽管 ZLIB 的校验和计算比 GZIP 性能更好并且产生的标头更小,但后者更常见(尤其是在 Web 中)。GZIP 受欢迎的主要原因是,Microsoft 始终难以区分原始 DEFLATE 和 ZLIB resp.HTTP 的deflate传输编码(请参阅 ZLIB 的FAQ-39;-)
| 归档时间: |
|
| 查看次数: |
384 次 |
| 最近记录: |