我正在尝试使用ZLIB .NET库中的字典,但ZStream
成员inflateSetDictionary
始终返回Z_STREAM_ERROR
。我已将此跟踪到Inflate.inflateSetDictionary
的子调用,该调用测试是否(z.istate.mode == DICT0
)
有没有人知道如何在这个库中使用字典或知道任何好的例子。我的代码的简化版本如下所示......
public class Form1 : System.Windows.Forms.Form
{
static private string sDictionary = "VALUE1,VALUE2,VALUE3";
class GZOutputStream : ZOutputStream
{
public GZOutputStream(Stream in_Renamed)
: base(in_Renamed)
{
byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
z.inflateSetDictionary(dictionary, dictionary.Length);
}
public GZOutputStream(Stream in_Renamed, int level)
: base(in_Renamed, level)
{
byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
z.deflateSetDictionary(dictionary, dictionary.Length);
}
}
class GZInputStream : ZInputStream
{
public GZInputStream(Stream in_Renamed)
: base(in_Renamed)
{
byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
z.inflateSetDictionary(dictionary, dictionary.Length);
}
public GZInputStream(Stream in_Renamed, int level)
: base(in_Renamed, level)
{
byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
z.deflateSetDictionary(dictionary, dictionary.Length);
}
}
public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
{
byte[] buffer = new byte[2000];
int len;
while ((len = input.Read(buffer, 0, 2000)) > 0)
{
output.Write(buffer, 0, len);
}
output.Flush();
}
private void compressFile(string inFile, string outFile)
{
FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
GZOutputStream outZStream = new GZOutputStream(outFileStream, 1); // zlibConst.Z_DEFAULT_COMPRESSION);
System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);
try
{
CopyStream(inFileStream, outZStream);
}
finally
{
outZStream.Close();
outFileStream.Close();
inFileStream.Close();
}
}
private void decompressFile(string inFile, string outFile)
{
FileStream outFileStream = new FileStream(outFile, FileMode.Create);
GZOutputStream outZStream = new GZOutputStream(outFileStream);
FileStream inFileStream = new FileStream(inFile, FileMode.Open);
try
{
CopyStream(inFileStream, outZStream);
}
finally
{
outZStream.Close();
outFileStream.Close();
inFileStream.Close();
}
}
}
答案 0 :(得分:1)
我设法通过字典使zlib压缩工作基于DotNetZip(nuget,github)。
由于api调用既不需要明显的,也不需要记录,也不需要简短,因此我将包装器放在它自己的nuget包ZlibWithDictionary(nuget,github)中。
用法很简单:
var compressed_byte_array = DeflateCompression.ZlibCompressWithDictionary(
bytes_array_to_compress,
CompressionLevel.Default,
null /*use default window size in bits; possible values 9-15*/,
CompressionStrategy.Default,
byte_array_of_dictionary
);
var decompressed_byte_array = DeflateCompression.ZlibDecompressWithDictionary(
compressed_byte_array,
byte_array_of_dictionary
);
如果您希望手动使用相应的zlib apis,则可以仔细阅读the source for the DeflateCompression
wrapper。
答案 1 :(得分:0)
虽然我没有完成解决我的问题,但我想分享我的进展......
解压缩数据流时,必须等到inflate(..)函数返回Z_NEED_DICT,因此我将以下代码段添加到ZLIB类ZInputStream和ZOutputStream中,以检查从z.inflate返回的错误值...
if (err == zlibConst.Z_NEED_DICT)
{
byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
z.inflateSetDictionary(dictionary, dictionary.Length);
err = z.inflate(flush_Renamed_Field);
}
另外,来自Inflate.inflate函数的以下代码部分似乎有错误...
case DICT4:
if (z.avail_in == 0)
return r; r = f;
z.avail_in--; z.total_in++;
z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked((int)0xff000000L);
z.istate.mode = DICT3;
goto case DICT3;
在此代码中,z.istate.need的值设置为值0xffffffffxx000000,这是不正确的,因为顶部位应为零,例如0x00000000xx0000。
以下更改修复了此问题..
z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L;