【问题标题】:Easiest way to compress in Python and decompress with decompress C# (and vice versa)在 Python 中压缩和使用 decompress C# 解压缩的最简单方法(反之亦然)
【发布时间】:2012-05-07 05:04:56
【问题描述】:

我有一个带有基于 Mono 的 C# 客户端和 Python 服务器的程序,它们通过 TCP/IP 套接字进行通信。消息主要使用二进制格式,但每条消息的最大部分通常是嵌入的 UTF-8 字符串(英文)。每条消息通常都很短(不到 100 字节),但有些消息可能更长(最多 64K)。交换了大量数据,我想通过在传输数据时压缩数据来减少消息大小和带宽使用。

我最初的研究没有发现任何明显兼容这 2 个标准库的东西。 Python 有一个 zlib 库,但我不能使用 C# 的 DeflateStream 或 GZipStream(因为它们需要一个我没有可用的外部 DLL)而且它似乎不适用于 SharpZipLib 的 ZipOutputStream(发出“错误-3 - 不正确的标题”响应)。 (那些不使用 Mono 的人可能更幸运 - 请参阅下面的 Duncan 的回答。)

我很想听听有关在此通信链路上启用压缩的简单方法,请记住,任何可能易于用一种语言实现的解决方案都需要在另一种语言中具有等效的解决方案。我会接受专门针对 UTF-8 字符串而不是二进制消息的解决方案,尽管首选是压缩整个字节流。

理想情况下,我希望将外部依赖降至最低,但我意识到这可能不切实际。

更新:在尝试使用 SharpZipLib 并在 Python 解码端遇到重复错误后,我真的可以使用已知有效的代码提出具体建议,而不仅仅是针对一种语言或另一种语言的压缩库的建议。

【问题讨论】:

  • SharpZip 具有与 zlib 兼容的实现 - InflaterInputStream 和 DeflaterOutputStream

标签: c# .net python mono compression


【解决方案1】:

你写道:

同样,两个标准库都提供 gzip 压缩,但 Python 期望在这种情况下使用文件,这是不切实际的。

实际上并非如此。 Python 的gzip.GZipFile() 类采用filenamefileobj。如果您想使用字符串,只需使用StringIO 对象作为fileobj

from gzip import GzipFile
from StringIO import StringIO
sio = StringIO()
with GzipFile(fileobj=sio, mode='wb') as gzip:
    gzip.write('uncompressed data')
compressed = sio.getvalue()

【讨论】:

  • 这是一个很好的观点,并且很有用。遗憾的是,我不能在 C# 端使用 gzip,所以我正在寻找替代方案。
【解决方案2】:

SharpZipLib 和 Python 库中的 BZip2 对我有用。以下是我测试的内容和方法:

一、C#程序(引用SharpZipLib):

using System;
using ICSharpCode.SharpZipLib.BZip2;
using System.IO;

namespace Test
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            var fStream = new FileStream("/home/konrad/output.bin", FileMode.Create);
            using(var writer = new StreamWriter(new BZip2OutputStream(fStream)))
            {
                for(var i = 0; i < 10; i++)
                {
                    writer.WriteLine("Line no {0}.", i);
                }
            }
        }
    }

}

然后是 Python:

from bz2 import BZ2File
import sys

f = BZ2File("/home/konrad/output.bin")
for line in f.readlines():
    sys.stdout.write(line)

接下来,运行 C# 程序。然后:

$ python ctest.py
Line no 0.
Line no 1.
Line no 2.
Line no 3.
Line no 4.
Line no 5.
Line no 6.
Line no 7.
Line no 8.
Line no 9.

我认为它也可以反过来工作。

【讨论】:

  • 这对我有用。 C# 中的 using 子句很关键 - 没有它,压缩永远不会发生。我猜压缩库要求在压缩数据并将其刷新到底层流之前处理相关流。
【解决方案3】:

我过去曾将 zlib 用于 .net,还有一些库封装了原生 zlib 库以提供托管解决方案。我需要做一些类似于你正在做的事情。我会直接在内存中进行压缩以进行较小的传输,然后压缩到文件中,然后从 url 下载文件并从文件中解压缩以获得更大的文件。

【讨论】:

    【解决方案4】:

    看来您使用的是 *nix 系统。如果是这种情况并且所有其他方法都失败了,您可以简单地使用系统库 (Mono.Unix.Native) 而无需担心找到合适的 .Net 库。

    【讨论】:

    • 不,不幸的是,我需要双方都独立于平台 - 这并没有解决 Python 方面的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多