我正在阅读数据(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'));
}
}
答案 0 :(得分:1)
你会发现DeflateStream在解压缩的数据方面受到很大限制。事实上,如果您期望整个文件,它将毫无用处。 ZIP文件中存在很多(大多数是小的)变体,而DeflateStream只会与其中的两个或三个相关。
最好的方法是使用专用库来读取Zip文件/流,如DotNetZip或SharpZipLib(有点不受维护)。
答案 1 :(得分:0)
您可以将流写入文件并在其上尝试我的工具Precomp。如果您这样使用它:
precomp -c- -v [name of input file]
将检测文件中的任何ZIP / gZip流,并报告一些详细信息(流的位置和长度)。此外,如果它们可以按位解压缩和重新压缩,则输出文件将包含解压缩的流。
Precomp在文件的任何位置检测到ZIP / gZip(和其他一些)流,因此您不必担心文件开头的头字节或垃圾。
如果它没有检测到这样的流,请尝试添加-slow
,即使它们没有ZIP / gZip标头,也会检测到deflate流。如果失败,您可以尝试-brute
甚至检测到缺少两个字节标题的deflate流,但这将非常慢并且可能导致误报。
之后,您将知道文件中是否存在(有效)deflate流,如果是,则附加信息应该可以帮助您使用zLib解压缩例程或类似方法正确解压缩其他报告。