如何解决Gzip Magic Number Missing [英] How to solve Gzip Magic Number Missing

查看:283
本文介绍了如何解决Gzip Magic Number Missing的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个字符串,我Gzip在服务器上,并使用WebClient类下载到客户端。当我尝试解压缩它,我得到错误消息,魔术数字丢失。我已经尝试过GZipStream类和ICSharpLib方法来解决这个问题,所以我很失望。



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



这是代码片段,似乎是令人讨厌的部分:

  byte [] response 
try {
response = client.DownloadData(Constants.GetSetting(SyncServer));
} catch {
MessageBox.Show(同步数据时出现问题,请尝试验证提供的凭据或稍后再试。,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];
...更多无关的表处理
}

任何帮助谢谢。 P.S。我使用Base64字符串能够在网络上来回传递。这可能是我在搞乱的区域,因为我没有在桌面应用程序和Web服务之前做过网络请求和响应。

解决方案

首先,我不认为该代码段是有效的,因为DownloadString返回(如预期的)一个String。



它使用下载数据时正确工作,当您使用DownloadString不正确?这是有道理的,因为它无法将Gzip数据解码为Unicode。



编辑:



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

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

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



行:

  memStream.ReadByte(); 

不应该在那里。您正在读取一个字节并将其丢弃。如果一切都像我们期望的那样,字节是0x1F,gzip幻数的一部分。



然后,我想你使用了错误的gzip类。您希望 GZipStream 。它的结构如下:

  GZipStream stream = new GZipStream(memStream,CompressionMode.Decompress);然后,直接使用StreamReader:








$ b

  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];

// ...
}


I have a string that I Gzip on the server and download to a client using the WebClient class. When I try to uncompress it, I get the error message that the Magic Number is missing. I have tried both the GZipStream class and the ICSharpLib methods of solving this, so I'm at a loss.

The compression/decompression works if I omit the step of downloading via the WebClient (using DownloadData which returns the data as byte[]), so I can only assume that there is some problem with the data getting truncated or corrupted some how, but since it's compressed data, I'm not sure how to debug this.

Here's the code snippet that seems to be the offending portion:

   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
}

Any help would be appreciated. P.S. I'm using the Base64 string to be able to pass back and forth across the web. This may in fact be the area I am messing up in since I've not done web requests and responses between a desktop app and a web service before.

解决方案

First, I don't think the snippet is valid, because DownloadString returns (as expected) a String.

Now, do I understand right that it works correctly when you use DownloadData and incorrectly when you use DownloadString? That makes sense because it is not valid to decode Gzip data as Unicode.

EDIT:

Okay, the ToBase64String and FromBase64String should be okay. But if you can avoid it and pass the byte[] directly, that would be good.

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

Then you would get rid of the first line of the function (the decode from base64). Note we're renaming encryptedFile to compressedFile.

The line:

memStream.ReadByte();

should not be there. You are reading a byte and discarding it. If everything is as we expect that byte is 0x1F, part of the gzip magic number.

Then, I think you're using the wrong gzip class. You want GZipStream. It is constructed like:

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

Then, you use StreamReader directly on that:

StreamReader sr = new StreamReader(stream);

It would help if you knew the encoding, but hopefully the default will be correct. Then it seems correct from there. So, overall we get the below.

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"];

    //...
}

这篇关于如何解决Gzip Magic Number Missing的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆