4

私はデータ(たまたまadCenterレポート)を読んでいますが、これは圧縮されているはずです。通常のストリームでコンテンツを読むと、数千バイトのジブリッシュが発生するので、これは妥当なようです。そこで、ストリームをDeflateStreamにフィードします。

まず、「ブロック長がその補数と一致しない」と報告します。簡単に検索すると、2バイトのプレフィックスがあることがわかります。実際、DeflateStreamを開く前にReadByte()を2回呼び出すと、例外はなくなります。

ただし、DeflateStreamは何も返さないようになりました。私は午後のほとんどをこれについてリードを追いかけて過ごしましたが、運がありませんでした。私を助けてください、StackOverflow、あなたは私の唯一の希望です!誰かが私が欠けているものを教えてもらえますか?

これがコードです。当然、テスト時に一度に2つのコメント付きブロックのうち1つだけを有効にしました。

_results = new List<string[]>();
using (Stream compressed = response.GetResponseStream())
  {
  // Skip the zlib prefix, which conflicts with the deflate specification
  compressed.ReadByte();  compressed.ReadByte();

  // Reports reading 3,000-odd bytes, followed by random characters
  /*byte[]  buffer    = new byte[4096];
  int     bytesRead = compressed.Read(buffer, 0, 4096);
  Console.WriteLine("Read {0} bytes.", bytesRead.ToString("#,##0"));
  string  content   = Encoding.ASCII.GetString(buffer, 0, bytesRead);
  Console.WriteLine(content);*/

  using (DeflateStream decompressed = new DeflateStream(compressed, CompressionMode.Decompress))
    {
    // Reports reading 0 bytes, and no output
    /*byte[]  buffer    = new byte[4096];
    int     bytesRead = decompressed.Read(buffer, 0, 4096);
    Console.WriteLine("Read {0} bytes.", bytesRead.ToString("#,##0"));
    string  content   = Encoding.ASCII.GetString(buffer, 0, bytesRead);
    Console.WriteLine(content);*/

    using (StreamReader reader = new StreamReader(decompressed))
      while (reader.EndOfStream == false)
        _results.Add(reader.ReadLine().Split('\t'));
    }
  }

最後の行から推測できるように、解凍されたコンテンツはTDTである必要があります。

楽しみのために、GZipStreamで解凍しようとしましたが、マジックナンバーが正しくないことが報告されています。MSのドキュメントには、「ダウンロードしたレポートはzip圧縮を使用して圧縮されています。レポートの内容を使用するには、レポートを解凍する必要があります」と書かれています。


これが最終的に機能したコードです。コンテンツをファイルに保存して読み直す必要がありました。これは合理的ではないようですが、使用している少量のデータについては、許容範囲内です。

WebRequest   request  = HttpWebRequest.Create(reportURL);
WebResponse  response = request.GetResponse();

_results = new List<string[]>();
using (Stream compressed = response.GetResponseStream())
  {
  // Save the content to a temporary location
  string  zipFilePath = @"\\Server\Folder\adCenter\Temp.zip";
  using (StreamWriter file = new StreamWriter(zipFilePath))
    {
    compressed.CopyTo(file.BaseStream);
    file.Flush();
    }

  // Get the first file from the temporary zip
  ZipFile  zipFile = ZipFile.Read(zipFilePath);
  if (zipFile.Entries.Count > 1)  throw new ApplicationException("Found " + zipFile.Entries.Count.ToString("#,##0") + " entries in the report; expected 1.");
  ZipEntry  report = zipFile[0];

  // Extract the data
  using (MemoryStream decompressed = new MemoryStream())
    {
    report.Extract(decompressed);
    decompressed.Position = 0;  // Note that the stream does NOT start at the beginning
    using (StreamReader reader = new StreamReader(decompressed))
      while (reader.EndOfStream == false)
        _results.Add(reader.ReadLine().Split('\t'));
    }
  }
4

2 に答える 2

1

DeflateStreamは、解凍するデータが大幅に制限されていることがわかります。実際、ファイル全体を期待している場合は、まったく役に立ちません。数百もの(ほとんどの場合小さな)ZIPファイルのバリエーションがあり、DeflateStreamはそのうちの2つまたは3つとしかうまくいきません。

最善の方法は、 DotNetZipやSharpZipLib(やや保守されていない)などのZipファイル/ストリームを読み取るための専用ライブラリを使用することです。

于 2011-02-19T00:32:22.500 に答える
0

ストリームをファイルに書き込んで、私のツールPrecompを試してみることができます。このように使用する場合:

precomp -c- -v [name of input file]

ファイル内のZIP/gZipストリームが検出され、詳細情報(ストリームの位置と長さ)が報告されます。さらに、それらをビットごとに同じように解凍および再圧縮できる場合、出力ファイルには解凍されたストリームが含まれます。

Precompは、ファイル内の任意の場所でZIP / gZip(およびその他の)ストリームを検出するため、ファイルの先頭にあるヘッダーバイトやガベージについて心配する必要はありません。

このようなストリームが検出されない場合は、を追加してみてください-slow。これにより、ZIP/gZipヘッダーがない場合でもdeflateストリームが検出されます。これが失敗した場合は-brute、2バイトのヘッダーがないデフレートストリームを検出することもできますが、これは非常に遅く、誤検知を引き起こす可能性があります。

その後、ファイルに(有効な)deflateストリームがあるかどうかがわかります。ある場合は、zLib解凍ルーチンなどを使用して他のレポートを正しく解凍するのに役立つ追加情報が必要です。

于 2011-02-19T00:37:59.223 に答える