C#实现文件Zip压缩
可适用于大文件压缩
压缩大文件时缓存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(); }
随便用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人