【问题标题】:compressing a string in C# and uncompressing in python在 C# 中压缩字符串并在 python 中解压缩
【发布时间】:2013-07-11 12:49:48
【问题描述】:

我正在尝试在 C#(.net 4)中的客户端程序上压缩一个大字符串,并使用 PUT 请求将其发送到服务器(django、python 2.7)。 理想情况下,我想在两端都使用标准库,所以我尝试使用 gzip。

我的 C# 代码是:

public static string Compress(string s) {
    var bytes = Encoding.Unicode.GetBytes(s);
    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream()) {
        using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
            msi.CopyTo(gs);
        }
        return Convert.ToBase64String(mso.ToArray());
    }
}

python代码是:

s = base64.standard_b64decode(request)
buff = cStringIO.StringIO(s)

with gzip.GzipFile(fileobj=buff) as gz:
    decompressed_data = gz.read()

它几乎可以工作了,但是输出是:{▯"▯c▯h▯a▯n▯g▯e▯d▯"▯} 当它应该是 {"changed"} 时,即每个其他字母都很奇怪. 如果我通过 decompressed_data[::2] 取出所有其他字符,那么它可以工作,但它有点像黑客,显然还有其他问题。

我想知道是否需要对 PUT 请求进行 base64 编码?这只需要 POST 吗?

【问题讨论】:

  • cStringIO.StringIO 理解 unicode 吗?

标签: c# python django compression gzip


【解决方案1】:

我认为主要问题可能是 C# 使用 UTF-16 编码字符串。这可能会产生与您类似的问题。与任何其他编码问题一样,我们可能需要一点运气,但我想您可以通过以下方式解决:

decompressed_data = gz.read().decode('utf-16')

在那里,decompressed_data 应该是Unicode,您可以将其视为进一步工作。

更新:这对我有用:

C 夏普

static void Main(string[] args)
    {
        FileStream f = new FileStream("test", FileMode.CreateNew);
        using (StreamWriter w = new StreamWriter(f))
        {
            w.Write(Compress("hello"));
        }
    }
    public static string Compress(string s)
    {
        var bytes = Encoding.Unicode.GetBytes(s);
        using (var msi = new MemoryStream(bytes))
        using (var mso = new MemoryStream())
        {
            using (var gs = new GZipStream(mso, CompressionMode.Compress))
            {
                msi.CopyTo(gs);
            }
            return Convert.ToBase64String(mso.ToArray());
        }
    }

Python

import base64
import cStringIO
import gzip

f = open('test','rb')
s = base64.standard_b64decode(f.read())
buff = cStringIO.StringIO(s)

with gzip.GzipFile(fileobj=buff) as gz:
    decompressed_data = gz.read()
    print decompressed_data.decode('utf-16')

如果没有decode('utf-16),它会打印在控制台中:

>>>h e l l o

它做得很好:

>>>hello

祝你好运,希望这会有所帮助!

【讨论】:

  • 谢谢,成功了。我真的需要对 PUT 请求进行 base64 编码吗?
  • 我不这么认为,据我所知,当您需要通过非二进制环境(如 XML、XMPP 等)传输二进制数据时使用 base64。HTTP 可能可以处理二进制您将不需要使用 base64 进行编码。
  • @eggbert 通过 HTTP 发送数据时(使用 POST 等),您需要编码您的请求(如果您发送的是文本,而不是二进制数据) .由于格式为key1=value1&key2=value2&...,因此需要对=&等一些字符进行编码。例如,如果要将a=1&b=2作为某个键的值发送,则应将其转换为@987654334 @。在 C# 中,您可以在 Python 中使用 HttpUtility.UrlEncodeurllib.urlencode
【解决方案2】:

它几乎可以工作,但输出是:{▯"▯c▯h▯a▯n▯g▯e▯d▯"▯} 当它应该是 {"changed"}

那是因为您使用 Encoding.Unicode 将字符串转换为字节开头。

如果您可以告诉 Python 使用哪种编码,您可以这样做 - 否则您需要在 C# 端使用与 Python 期望匹配的编码。

如果您可以在两边都指定它,我建议使用 UTF-8 而不是 UTF-16。即使您正在压缩,将数据大小减半(在许多情况下)开始时不会有什么坏处:)

我也有点怀疑这条线:

buff = cStringIO.StringIO(s)

s 真的不是文本数据 - 它是压缩的 二进制 数据,应该这样对待。可能没问题 - 只是值得检查是否有更好的方法。

【讨论】:

  • 做 buff = cStringIO.StringIO(s) 的唯一原因是把它变成一个文件对象,因为 gzip.GzipFile 不带字符串
  • @eggbert:但你并没有真正字符串——你有二进制数据。这就是我发现 Python 令人沮丧的地方,因为它将字符串和二进制数据视为在太多地方是等价的。这可能很好,但它让我畏缩。
  • 我不得不说我同意这一点,它有时令人沮丧,但当你经常使用它时,你就会习惯它:) Python 3 试图以某种方式解决这个问题,但它仍然很容易获得二进制和普通字符串之间的混淆:)(尽管最后它们几乎相同,一堆字节)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多