4

我正在阅读应该压缩的数据(adCenter 报告,碰巧)。用普通流读取内容,我得到了几千字节的乱码,所以这似乎是合理的。所以我将流提供给 DeflateStream。

首先,它报告“块长度与其补码不匹配”。一个简短的搜索表明有一个双字节前缀,实际上如果我在打开 DeflateStream 之前调用 ReadByte() 两次,异常就会消失。

但是,DeflateStream 现在什么都不返回。我花了大部分下午的时间在这方面寻找线索,但没有运气。帮助我,StackOverflow,你是我唯一的希望!谁能告诉我我错过了什么?

这是代码。自然,我在测试时一次只启用了两个注释块之一。

_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 只能处理其中的两个或三个。

最好的方法可能是使用专用库来读取 Zip 文件/流,如DotNetZip或 SharpZipLib(有点未维护)。

于 2011-02-19T00:32:22.500 回答
0

您可以将流写入文件并在其上尝试我的工具Precomp。如果你像这样使用它:

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

将检测文件中的任何 ZIP/gZip 流,并报告一些详细信息(流的位置和长度)。此外,如果它们可以逐位相同地解压缩和重新压缩,则输出文件将包含解压缩的流。

Precomp 检测文件中任何位置的 ZIP/gZip(和其他一些)流,因此您不必担心文件开头的标题字节或垃圾。

如果它没有检测到这样的流,请尝试添加-slow,它会检测 deflate 流,即使它们没有 ZIP/gZip 标头。如果这失败了,您-brute甚至可以尝试检测缺少两字节标头的放气流,但这会非常慢并且可能导致误报。

之后,您将知道文件中是否有(有效的)deflate 流,如果有,附加信息应该可以帮助您使用 zLib 解压缩例程或类似程序正确解压缩其他报告。

于 2011-02-19T00:37:59.223 回答