C# 解压缩gzipstream时出错--GZip头中的幻数不正确

C# 解压缩gzipstream时出错--GZip头中的幻数不正确,c#,.net,C#,.net,我正在使用C#System.IO类(framework 4.0)来压缩一个图像,该图像通过FileDialog从文件系统中提取,然后作为varbinary(max)数据类型插入SQL Server数据库。我遇到的问题是,当我从数据库中取出数据并尝试解压缩时,我会得到一条附加消息的主题错误——确保您正在传递gzip流 获取文件的代码: OpenFileDialog dlgOpen = new OpenFileDialog(); if (dlgOpen.ShowDialog() =

我正在使用C#
System.IO
类(framework 4.0)来压缩一个图像,该图像通过
FileDialog
从文件系统中提取,然后作为
varbinary(max)
数据类型插入SQL Server数据库。我遇到的问题是,当我从数据库中取出数据并尝试解压缩时,我会得到一条附加消息的主题错误——确保您正在传递gzip流

获取文件的代码:

    OpenFileDialog dlgOpen = new OpenFileDialog();

    if (dlgOpen.ShowDialog() == DialogResult.OK)
    {
        FileStream fs = File.OpenRead(dlgOpen.FileName);
        byte[] picbyte1 = new byte[fs.Length];
        byte[] picbyte = Compress(picbyte1);
        fs.Read(picbyte, 0, System.Convert.ToInt32(picbyte.Length));
        String ImageName = dlgOpen.FileName;
        //String bs64OfBytes = Convert.ToBase64String(picbyte);
        fs.Close();
        //additional code inserts into database
        ....

     }
压缩方法:

        private static byte[] Compress(byte[] data)
        {
            var output = new MemoryStream();
            using (var gzip = new GZipStream(output, CompressionMode.Compress, true))
            {
                gzip.Write(data, 0, data.Length);
                gzip.Close();
            }
            return output.ToArray();
        }
        private static byte[] Decompress(byte[] data)
        {
            var output = new MemoryStream();
            var input = new MemoryStream();
            input.Write(data, 0, data.Length);
            input.Position = 0; 

            using (var gzip = new GZipStream(input, CompressionMode.Decompress, true))
            {
                var buff = new byte[64];//also used 32
                var read = gzip.Read(buff, 0, buff.Length);//error occurs here

                while (read > 0)
                {
                    output.Write(buff, 0, read);
                    read = gzip.Read(buff, 0, buff.Length);
                }

                gzip.Close();
            }
            return output.ToArray();
        }
解压缩方法:

        private static byte[] Compress(byte[] data)
        {
            var output = new MemoryStream();
            using (var gzip = new GZipStream(output, CompressionMode.Compress, true))
            {
                gzip.Write(data, 0, data.Length);
                gzip.Close();
            }
            return output.ToArray();
        }
        private static byte[] Decompress(byte[] data)
        {
            var output = new MemoryStream();
            var input = new MemoryStream();
            input.Write(data, 0, data.Length);
            input.Position = 0; 

            using (var gzip = new GZipStream(input, CompressionMode.Decompress, true))
            {
                var buff = new byte[64];//also used 32
                var read = gzip.Read(buff, 0, buff.Length);//error occurs here

                while (read > 0)
                {
                    output.Write(buff, 0, read);
                    read = gzip.Read(buff, 0, buff.Length);
                }

                gzip.Close();
            }
            return output.ToArray();
        }

您需要插入一行并删除另一行:

FileStream fs = File.OpenRead(dlgOpen.FileName);
byte[] picbyte1 = new byte[fs.Length];
fs.Read(picbyte1, 0, (int)fs.Length); // <-- Add this one
byte[] picbyte = Compress(picbyte1);
// fs.Read(picbyte, 0, System.Convert.ToInt32(picbyte.Length)); // <-- And remove this one
// ...
因此,您保存了原始文件的第一部分,而不是压缩的部分(但保存的字节数与压缩的字节数相对应)。如果您将其发送到数据库并将其读回,则解压缩程序不会找到它的神奇数字

作为改进,您可以更改以下行:

FileStream fs = File.OpenRead(dlgOpen.FileName);
byte[] picbyte1 = new byte[fs.Length];
fs.Read(picbyte1, 0, (int)fs.Length); // line that I suggested to add
可能改为:

byte[] picbyte1 = File.ReadAllBytes(dlgOpen.FileName);

如果您
Compress()
Decompress()
之间没有数据库,结果如何?换句话说:你用压缩的输出直接作为解压的输入,这行吗?通过这种方式,您可以发现您的代码或从数据库到数据库的
代码中是否有错误。为什么要压缩一个填充了零字节的缓冲区?使用调试器并在运行时检查所有变量。你会发现一些奇怪的东西。如果我直接将Compress的输出发送到Decompress,我会得到同样的错误。我还检查了要压缩的输入,它显示有字节,她需要不止一行,
Read(
不能保证读取您在
fs.Length
中请求的字节数,您需要循环,直到用读取返回的
int
填充字节数组,以抵消第二个参数中当前作为
0
的值(第三个参数也用相同的偏移量减去
fs.Length
。@Scott:我想你是对的。但我知道文件流是缓冲的,可以用这种方式来实现(.Net 2.0及更高版本)。我认为这是理所当然的(但从未验证过)。我用这段代码做了一个测试,它成功了。但是你的建议必须记住。如果这条消息的海报仍然有问题,这部分需要注意。@Scott另一次:我想
File.ReadAllBytes(dlgOpen.FileName)
会更好。我已将其添加到答案中。是的,我将在第一条评论中提到这一点,但我忘记了函数的名称。