[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;
}

 

 

posted on 2020-06-09 14:21  黄小二  阅读(729)  评论(0编辑  收藏  举报