在 C# 中解压数据

发布于 2025-01-08 15:00:13 字数 2818 浏览 0 评论 0原文

我是 C# 新手,正在编写一个简单的 Web 服务。它获取 zip 文件并将其解压缩到文件系统中。在 C# 代码中是:

[WebMethod]
public String SetZip(string device_id, string file)
{
    if (device_id == null || device_id.Length == 0)
    {
        return "10;no auth data";
    }

    StringBuilder output = new StringBuilder();

    if (direcory == null)
    {
        return output.ToString();
    }

    string dirname = "c:\\temp\\" + direcory + "\\";

    if (!System.IO.Directory.Exists(dirname))
    {
        System.IO.Directory.CreateDirectory(dirname);
    }

    string filename = dirname + "file1.txt";

    string text = UnZipStr(Convert.FromBase64String(file));

    File.WriteAllText(filename, text);

    output.AppendLine("0;done");

    return output.ToString();
}

public static string UnZipStr(byte[] input)
{
    using (MemoryStream memstream = new MemoryStream())
    {
        using (MemoryStream inputStream = new MemoryStream(input))
        {
            using (DeflateStream gzip =
              new DeflateStream(inputStream, CompressionMode.Decompress))
            {
                using (StreamReader reader =
                  new StreamReader(gzip, System.Text.Encoding.UTF8))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
}

并从 java 代码发送 zip 数据:

    void callService(byte[] xmlData) {
    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
    request.addProperty("device_id", AGENT);

    Deflater deflater = new Deflater();
    deflater.setInput(xmlData);
    deflater.finish();

     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     byte[] buf = new byte[1024];
     while (!deflater.finished()) {
         int byteCount = deflater.deflate(buf);
         baos.write(buf, 0, byteCount);
     }
     deflater.end();

     byte[] compressedBytes = baos.toByteArray();

    request.addPropertyIfValue("file", org.kobjects.base64.Base64.encode(compressedBytes));...}

在 C# 代码中,从 StreamReader 读取数据时出现异常

SoapFault - faultcode: 'soap:Server' faultstring:     'System.Web.Services.Protocols.SoapException: ---> InvalidDataException: Block length does    not correspond to the complement.
System.IO.Compression.Inflater.DecodeUncompressedBlock(Boolean& end_of_block)
System.IO.Compression.Inflater.Decode()
System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
System.IO.StreamReader.ReadBuffer()
System.IO.StreamReader.ReadToEnd()
Service.UnZipStr(Byte[] input) в c:\inetpub\wwwroot\WebSite\App_Code\Service.cs: at 94
Service.SetZip(String device_id, String file) в c:\inetpub\wwwroot\WebSite\App_Code    \Service.cs: at 73

我做错了什么?

I'm new at C#, I writing a simple web service. It takes the zip file and decompress it in file system. In C# code is:

[WebMethod]
public String SetZip(string device_id, string file)
{
    if (device_id == null || device_id.Length == 0)
    {
        return "10;no auth data";
    }

    StringBuilder output = new StringBuilder();

    if (direcory == null)
    {
        return output.ToString();
    }

    string dirname = "c:\\temp\\" + direcory + "\\";

    if (!System.IO.Directory.Exists(dirname))
    {
        System.IO.Directory.CreateDirectory(dirname);
    }

    string filename = dirname + "file1.txt";

    string text = UnZipStr(Convert.FromBase64String(file));

    File.WriteAllText(filename, text);

    output.AppendLine("0;done");

    return output.ToString();
}

public static string UnZipStr(byte[] input)
{
    using (MemoryStream memstream = new MemoryStream())
    {
        using (MemoryStream inputStream = new MemoryStream(input))
        {
            using (DeflateStream gzip =
              new DeflateStream(inputStream, CompressionMode.Decompress))
            {
                using (StreamReader reader =
                  new StreamReader(gzip, System.Text.Encoding.UTF8))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
}

And send zip data from java code:

    void callService(byte[] xmlData) {
    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
    request.addProperty("device_id", AGENT);

    Deflater deflater = new Deflater();
    deflater.setInput(xmlData);
    deflater.finish();

     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     byte[] buf = new byte[1024];
     while (!deflater.finished()) {
         int byteCount = deflater.deflate(buf);
         baos.write(buf, 0, byteCount);
     }
     deflater.end();

     byte[] compressedBytes = baos.toByteArray();

    request.addPropertyIfValue("file", org.kobjects.base64.Base64.encode(compressedBytes));...}

At C# code I have Exception when read data from StreamReader

SoapFault - faultcode: 'soap:Server' faultstring:     'System.Web.Services.Protocols.SoapException: ---> InvalidDataException: Block length does    not correspond to the complement.
System.IO.Compression.Inflater.DecodeUncompressedBlock(Boolean& end_of_block)
System.IO.Compression.Inflater.Decode()
System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
System.IO.StreamReader.ReadBuffer()
System.IO.StreamReader.ReadToEnd()
Service.UnZipStr(Byte[] input) в c:\inetpub\wwwroot\WebSite\App_Code\Service.cs: at 94
Service.SetZip(String device_id, String file) в c:\inetpub\wwwroot\WebSite\App_Code    \Service.cs: at 73

What I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

也只是曾经 2025-01-15 15:00:13

编辑:我一直在研究,有一种方法可以从 Java 生成 C# 识别的 DEFLATE 格式数据:您必须使用 Deflater(int,boolean) 构造函数。因此,将您的 Java 代码更改为:

Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
deflater.setInput(xmlData);
deflater.finish();

原因是默认情况下 deflater 会发出 ZLIB 标头和校验和,这是 C# DeflateStream 所不期望的。


看来 Java 和 C# 在“deflate”压缩算法的确切种类上并不一致,但根据我的测试,“gzip”应该可以工作:

这在 Java 中压缩 xmlData

ByteArrayOutputStream baos = new ByteArrayOutputStream()
OutputStream out = new GZIPOutputStream(baos);
out.write(xmlData);
out.close();
byte[] compressedBytes = baos.toByteArray();

这解压缩 input在 C# 中:

using (MemoryStream inputStream = new MemoryStream(input))
{
  using (GZipStream gzip = new GZipStream(inputStream, CompressionMode.Decompress))
  {
    using (StreamReader reader = new StreamReader(gzip, System.Text.Encoding.UTF8))
    {
      return reader.ReadToEnd();
    }
  }
}

Edit: I've been digging around and there is a way to generate DEFLATE format data from Java that C# recognizes: you have to use the Deflater(int,boolean) constructor. So change your Java code to:

Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
deflater.setInput(xmlData);
deflater.finish();

The reason is that by default the deflater emits a ZLIB header and checksum, which the C# DeflateStream doesn't expect.


It seems that Java and C# don't agree on the exact variety of "deflate" compression algorithm, but by my tests "gzip" should work:

This compresses xmlData in Java:

ByteArrayOutputStream baos = new ByteArrayOutputStream()
OutputStream out = new GZIPOutputStream(baos);
out.write(xmlData);
out.close();
byte[] compressedBytes = baos.toByteArray();

This decompress input in C#:

using (MemoryStream inputStream = new MemoryStream(input))
{
  using (GZipStream gzip = new GZipStream(inputStream, CompressionMode.Decompress))
  {
    using (StreamReader reader = new StreamReader(gzip, System.Text.Encoding.UTF8))
    {
      return reader.ReadToEnd();
    }
  }
}
琉璃繁缕 2025-01-15 15:00:13

看起来@Joni Salonen 已经给出了 deflate 问题的答案,所以我想添加一些关于架构的内容。要隔离问题,您应该将这两个问题分开。首先,您需要删除一个压缩文件。然后你需要给它放气。然后,分别关注问题领域。您稍后可以随时“管道”这两个问题。

顺便说一句,在许多情况下拥有原始 zip 文件很有用。当某些事情没有按计划进行时,尤其是当事情没有按计划进行时,它就成为一个安全网。如果您只有一次捕获该文件的机会。

It looks like @Joni Salonen has given an answer to the deflate problem, so I want to add a bit about architecture. To isolate the issue, you should separate the two concerns. First, you need to drop a zipped file. Then you need to deflate it. Then, focus on the problem area separately. You can always "pipeline" the two concerns later.

BTW, it is useful to have the raw zip file in many instances. It becomes a safety net when something does not work as planned, esp. if you only have one chance to capture the file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文