1

我有一个字符串,我在服务器上 Gzip 并使用 WebClient 类下载到客户端。当我尝试解压缩它时,我收到了缺少幻数的错误消息。我已经尝试过 GZipStream 类和 ICSharpLib 方法来解决这个问题,所以我很茫然。

如果我省略通过 WebClient 下载的步骤(使用将数据返回为 byte[] 的 DownloadData),压缩/解压缩将起作用,所以我只能假设数据被截断或损坏了一些问题,但是因为它是压缩数据,我不知道如何调试它。

这是似乎有问题的代码片段:

   byte[] response
   try {
        response = client.DownloadData(Constants.GetSetting("SyncServer"));
   } catch {
        MessageBox.Show("There was a problem synchronizing the data. Please try verify the supplied credentials or try again later.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
   }

   int rows = SQLiteAPI.ImportStatHistoryXML(CurrentUser.User, myCampus, Convert.ToBase64String(response));

public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, string xmlFile) {
            byte[] encryptedFile = Convert.FromBase64String(xmlFile);
            MemoryStream memStream = new MemoryStream(encryptedFile);
            memStream.ReadByte();
            GZipInputStream stream = new GZipInputStream(memStream);
            MemoryStream memory = new MemoryStream();
            byte[] writeData = new byte[4096];
            int size;

            while (true) {
                size = stream.Read(writeData, 0, writeData.Length);
                if (size > 0) {
                    memory.Write(writeData, 0, size);
                } else {
                    break;
                }
            }
            stream.Close();
            memory.Position = 0;
            StreamReader sr = new StreamReader(memory);
            string decompressed = sr.ReadToEnd();
            DataSet tempSet = new DataSet();
            StringReader xmlReader = new StringReader(decompressed);
            tempSet.ReadXml(xmlReader);
            DataTable statTable = tempSet.Tables["Stats"];
...more unrelated processing of the table
}

任何帮助,将不胜感激。PS 我使用 Base64 字符串能够在网络上来回传递。这实际上可能是我搞砸的领域,因为我之前没有在桌面应用程序和 Web 服务之间完成 Web 请求和响应。

4

1 回答 1

6

首先,我不认为该片段是有效的,因为 DownloadString 返回(如预期)一个字符串。

现在,我是否理解正确的是,当您使用 DownloadData 时它可以正常工作,而当您使用 DownloadString 时它不正确?这是有道理的,因为将 Gzip 数据解码为 Unicode 是无效的。

编辑:

好的,ToBase64String 和 FromBase64String 应该没问题。但是,如果您可以避免它并直接传递 byte[] ,那就太好了。

public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, byte[] compressedFile) {

然后你会摆脱函数的第一行(来自base64的解码)。请注意,我们将 encryptedFile 重命名为compressedFile。

该行:

memStream.ReadByte();

不应该在那里。您正在读取一个字节并丢弃它。如果一切都如我们所料,字节为 0x1F,它是 gzip 幻数的一部分。

然后,我认为您使用了错误的 gzip 类。你想要GZipStream。它的构造如下:

GZipStream stream = new GZipStream(memStream, CompressionMode.Decompress);

然后,您直接在上面使用 StreamReader:

StreamReader sr = new StreamReader(stream);

如果您知道编码会有所帮助,但希望默认值是正确的。然后从那里看起来是正确的。所以,总的来说,我们得到了以下结果。

public static int ImportStatHistoryXML(Person tempPerson, Campus tempCampus, byte[] compressedFile) {
    MemoryStream memStream = new MemoryStream(compressedFile);
    GZipStream gzStream = new GZipStream(memStream, CompressionMode.Decompress);
    StreamReader sr = new StreamReader(gzStream);
    string decompressed = sr.ReadToEnd();
    DataSet tempSet = new DataSet();
    StringReader xmlReader = new StringReader(decompressed);
    tempSet.ReadXml(xmlReader);
    DataTable statTable = tempSet.Tables["Stats"];

    //...
}
于 2009-06-22T06:49:48.193 回答