C#实现文件Zip压缩

原文地址:https://blog.csdn.net/xinxin_2011/article/details/100535917?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-7-100535917.pc_agg_new_rank&utm_term=c%23+%E5%8E%8B%E7%BC%A9%E5%A4%A7%E6%96%87%E4%BB%B6&spm=1000.2123.3001.4430

 

可适用于大文件压缩

压缩大文件时缓存buffer创建的时候出现溢出。那么这个缓存创建了多大呢?fs.Length!!没错,文件多大咱就创建多大,这样相当于把整个文件放入内存
解决思路是开辟一个固定大小的缓存区,循环读取文件进行压缩,但是这里有个问题,压缩时是先写入ZipEntry再写入文件数据的,而ZipEntry里面包含了crc信息,不把文件读完,就计算不出来crc。这里采用读取两遍文件的策略,第一遍计算crc,第二遍再写入文件数据。
修改之后,foreach循环里的代码如下,直接上代码

复制代码
        /// <summary>
        /// 压缩大文件
        /// </summary>
        /// <param name="args"></param>
        /// <param name="password"></param>
        public static void ZipFileMainBest(string[] args, string password)
        {

            List<string> files = new List<string>();
            string[] filetypes;
            if (ConfigurationManager.AppSettings["FileType"].ToString() != "")
            {
                filetypes = ConfigurationManager.AppSettings["FileType"].ToString().Split(';');
                Director(args[0], filetypes, files);
            }
            else
            {
                Director(args[0], files);
            }

            int count = files.Count;
            string[] ff = new string[count];

            int i = 0;
            foreach (var item in files)
            {
                ff[i] = item.ToString();
                i++;
            }

            string[] filenames = ff; //Directory.GetFiles(args[0]);
            if (filenames.Length > 0)
            {
                ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

                s.SetLevel(6); // 0 - store only to 9 - means best compression 

                s.Password = md5.encrypt(password);
                s.Password = password; //md5.encrypt(password);
                Crc32 crc = new Crc32();
                foreach (string file in filenames)
                {
                    int readlen = 4096000;
                    FileStream fs = File.OpenRead(file);
                    byte[] buffer = new byte[4096000];       // 每次4M
                    Array arr = file.Split('\\');
                    string le = arr.GetValue(arr.Length - 1).ToString();
                    ZipEntry entry = new ZipEntry(le);
                    entry.DateTime = DateTime.Now;
                    entry.Size = fs.Length;

                    long remaindSize = fs.Length;
                    // 计算crc
                    crc.Reset();
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);
                        remaindSize -= readlen;

                        crc.Update(buffer, 0, readlen);
                    }
                    entry.Crc = crc.Value;
                    s.PutNextEntry(entry);

                    // 压缩数据
                    readlen = 4096000;
                    remaindSize = fs.Length;
                    fs.Seek(0, SeekOrigin.Begin);
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);
                        remaindSize -= readlen;
                        s.Write(buffer, 0, readlen);
                    }
                    s.Flush();
                    fs.Close();
                }

                s.Finish();
                s.Close();
            }
        }
复制代码

 

核心代码

复制代码
if (filenames.Length > 0)
            {
                ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

                s.SetLevel(6); // 0 - store only to 9 - means best compression 

                s.Password = md5.encrypt(password);
                s.Password = password; //md5.encrypt(password);
                Crc32 crc = new Crc32();
                foreach (string file in filenames)
                {
                    int readlen = 4096000;
                    FileStream fs = File.OpenRead(file);
                    byte[] buffer = new byte[4096000];       // 每次4M
                    Array arr = file.Split('\\');
                    string le = arr.GetValue(arr.Length - 1).ToString();
                    ZipEntry entry = new ZipEntry(le);
                    entry.DateTime = DateTime.Now;
                    entry.Size = fs.Length;

                    long remaindSize = fs.Length;
                    // 计算crc  ,不计算也可行
                    crc.Reset();
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);
                        remaindSize -= readlen;

                        crc.Update(buffer, 0, readlen);
                    }
                    entry.Crc = crc.Value;
                    s.PutNextEntry(entry);

                    // 压缩数据
                    readlen = 4096000;
                    remaindSize = fs.Length;
                    fs.Seek(0, SeekOrigin.Begin);
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);//fs 是循序读取文件流
                        remaindSize -= readlen;
                        s.Write(buffer, 0, readlen);
                    }
                    s.Flush();
                    fs.Close();
                }

                s.Finish();
                s.Close();
            }
复制代码

 

posted @   JackDDD  阅读(1442)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示