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 サービスの間で Web 要求と応答を行ったことがないため、実際には私が混乱している領域である可能性があります。

4

1 に答える 1

6

まず、DownloadString は (予想どおり) 文字列を返すため、スニペットは有効ではないと思います。

さて、DownloadData を使用すると正しく動作し、DownloadString を使用すると正しく動作しないことを理解していますか? Gzip データを Unicode としてデコードすることは有効ではないため、これは理にかなっています。

編集:

わかりました、ToBase64String と FromBase64String は問題ないはずです。しかし、それを避けて byte[] を直接渡すことができれば、それでよいでしょう。

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

次に、関数の最初の行 (base64 からのデコード) を取り除きます。暗号化ファイルの名前を圧縮ファイルに変更していることに注意してください。

この線:

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 に答える