[C#][压缩] 组件对比
System.IO.Compression v.4.3.0 | SharpZipLib v.1.2.0 | SevenZipSharp.Net45 v.1.0.19 |
.Net 及 .Net Core 自带, Core版本有对于Unix 字符的读取支持 |
对于Unix 字符的读取支持 | |
.Net版本无Unix 特殊字符支持 | 无Unix 特殊字符支持 |
需要 7z.dll 引用 以流方式读取某些文件会报错,需要以文件方式读取 |
https://www.nuget.org/packages/System.IO.Compression/ | https://www.nuget.org/packages/SharpZipLib/ | https://www.nuget.org/packages/SevenZipSharp.Net45/ |
System.IO.Compression
using System.IO.Compression; public void ZipArchive_Extract() { var file = @"D:\0.Work\FtpTest-compress\Unix_file.zip"; var dir = @"D:\0.Work\FtpTest-compress\1\"; // ex.1 https://stackoverflow.com/questions/42262013/how-can-i-get-the-valid-entries-of-a-ziparchive-when-one-them-contains-illegal-c // ex.2.ZipFile.ExtractToDirectory(file, @"D:\0.Work\FtpTest-compress\1\"); // 文件名、目录名或卷标语法不正确。 : // 'D:\0.Work\FtpTest-compress\1\HZRHDX-20190705-002-000001||at||1.pdf' using var fs = new FileStream(file, FileMode.Open, FileAccess.Read); var bytes = new byte[fs.Length]; fs.Read(bytes, 0, bytes.Length); using var stream = new MemoryStream(bytes); // 这里只是示例 文件->流->字节缓冲区 的转换方式,实际上可以进行删减 using var zip = new ZipArchive(stream, ZipArchiveMode.Read, true, Encoding.UTF8); foreach (var entry in zip.Entries.ToList()) { var fullName = dir + ReplaceInvalidChars(entry.FullName); var path = Path.GetDirectoryName(fullName); if (!Directory.Exists(path)) Directory.CreateDirectory(path); entry.ExtractToFile(fullName, true); // 或者可以直接读取流 Stream entryStream = entry.Open() } } /// <summary> /// 替换掉(文件名包含的)特殊字符 /// </summary> public string ReplaceInvalidChars(string filename, string replaceStr = "_") { var invalidStr = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); foreach (var c in invalidStr) { filename = filename.Replace(c.ToString(), replaceStr); } return filename; }
SharpZipLib
using ICSharpCode.SharpZipLib.Zip; public void SharpZipLib_Entries() { var file = @"xxx.zip"; using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read)) { using (var archive = new ZipFile(stream)) { } } } public void SharpZipLib_Extract() { var file = @"xxx.zip"; using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read)) { new FastZip().ExtractZip(file, @"D:\0.Work\FtpTest-compress\1\", ""); } }
SevenZipSharp.Net45
using SevenZip; public void SevenZip_ExtractStream0() { var file = @"D:\0.Work\FtpTest-compress\Unix_File.zip"; var dir = @"D:\0.Work\FtpTest-compress\1\"; var nameKey = "06198101000734947685"; var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); var data = new byte[fileStream.Length]; fileStream.Read(data, 0, data.Length); // 直接读取 Stream流格式会报错,所以暂时做一个转义(先临时保存) // Invalid archive: open/read error! Is it encrypted and a wrong password was provided? // If your archive is an exotic one, it is possible that SevenZipSharp has no signature for its format and thus decided it is TAR by mistake. var tmpZipFullName = CreateTmpFile(data, nameKey); using (var zip = new SevenZipExtractor(tmpZipFullName)) { // 解压所有文件到指定目录 // zip.ExtractArchive(targetDirectory); // 解压单个文件到指定目录 // zip.ExtractFiles(targetDirectory, 包内的文件索引或者文件名); // 包内单个文件读取到字节缓冲区 //foreach (var entry in zip.ArchiveFileData) //{ // using (var memoryStream = new MemoryStream()) // { // zip.ExtractFile(entry.FileName, memoryStream); // var entryBuffer = new byte[memoryStream.Length]; // memoryStream.Position = 0; // memoryStream.Read(entryBuffer, 0, entryBuffer.Length); // } //} // 解压单个文件到指定目录(允许改文件名,以流方式写入) foreach (var entry in zip.ArchiveFileData) { var newFullName = dir + ReplaceInvalidChars(entry.FileName); var newPath = Path.GetDirectoryName(newFullName); if (!string.IsNullOrWhiteSpace(newPath) && !Directory.Exists(newPath)) Directory.CreateDirectory(newPath); using (var fs = new FileStream(newFullName, FileMode.OpenOrCreate, FileAccess.Write)) { zip.ExtractFile(entry.FileName, fs); // 将包内的文件以流的方式写入 } } } // enf.of using (var zip = new SevenZipExtractor(tmpZipFullName)) } private static string CreateTmpFile(byte[] data, string nameKey) { // 直接读取 Stream流格式会报错,所以暂时做一个转义(先临时保存) // Invalid archive: open/read error! Is it encrypted and a wrong password was provided? // If your archive is an exotic one, it is possible that SevenZipSharp has no signature for its format and thus decided it is TAR by mistake. var dir = @"D:\0.Work\FtpTest-compress\1"; var baseFolder = dir + Path.DirectorySeparatorChar + "TmpZip" + Path.DirectorySeparatorChar; if (!System.IO.Directory.Exists(baseFolder)) Directory.CreateDirectory(baseFolder); var tmpZipFullName = string.Format("{0}{1}_{2}.zip" , baseFolder, DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff"), nameKey); if (System.IO.File.Exists(tmpZipFullName)) System.IO.File.Delete(tmpZipFullName); using (var fs1 = new FileStream(tmpZipFullName, FileMode.Create, FileAccess.Write)) { fs1.Write(data, 0, data.Length); } return tmpZipFullName; }