C# 解压zip乱码问题(已解决)

需求:解压一个目录下所有压缩文件到所在目录

时间:2023-07-31
问题:zip解压乱码,rar不会(巨硬nb)
原因:GBK编码问题

版本
ICSharpCode.SharpZipLib0.85
SharpCompress0.32
SharpZipLib1.33

SharpZipLib 必须是 1.33

一共三个文件详见,其他的不要看
在这里插入图片描述
ArchiveManager.cs
使用第二个文件封装一个解压,可以写一个文件,偷懒多封装一层

来自于ChatGPT …

using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using SharpCompress.Archives;
using SharpCompress.Common;
using static ICSharpCode.SharpZipLib.Zip.FastZip;

public class ArchiveManager
{

    private string rootPath;
    public ArchiveManager(string rootPath)
    {
        this.rootPath = rootPath;
    }


    /// <summary>
    /// 主程序
    /// </summary>
    public void ProcessArchives()
    {
        string[] archiveFiles = Directory.GetFiles(rootPath, "*.rar", SearchOption.AllDirectories)
                                       .Union(Directory.GetFiles(rootPath, "*.zip", SearchOption.AllDirectories))
                                       .ToArray();

        foreach (string archiveFile in archiveFiles)
        {
            Console.WriteLine(archiveFile);
            string extractionPath = Path.Combine(Path.GetDirectoryName(archiveFile), Path.GetFileNameWithoutExtension(archiveFile));

            if (archiveFile.EndsWith(".zip"))
            {
                ExtractZipFile2(archiveFile, extractionPath);
            }
            else if (archiveFile.EndsWith(".rar"))
            {
                ExtractRarFile(archiveFile, extractionPath);
            }
        }
    }



   /// <summary>
   /// zip
   /// </summary>
   /// <param name="zipFilePath"></param>
   /// <param name="extractionPath"></param>
    private void ExtractZipFile(string zipFilePath, string extractionPath)
    {
        using (var archive = ZipFile.OpenRead(zipFilePath))
        {
            foreach (var entry in archive.Entries)
            {
                if (!entry.FullName.EndsWith("/"))
                {
                    string entryPath = Path.Combine(extractionPath, DecodeUtf8(entry.FullName));
                    string entryDir = Path.GetDirectoryName(entryPath);

                    if (!Directory.Exists(entryDir))
                    {
                        Directory.CreateDirectory(entryDir);
                    }

                    using (Stream stream = entry.Open())
                    {
                        using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding("GB18030")))
                        {
                            File.WriteAllText(entryPath, reader.ReadToEnd(), Encoding.GetEncoding("GB18030"));
                        }
                    }
                }
            }
        }
    }


    /// <summary>
    ///  单独封装一个
    /// </summary>
    /// <param name="zipFilePath"></param>
    /// <param name="extractionPath"></param>
    private void ExtractZipFile2(string zipFilePath, string extractionPath)
    {
        // 新建文件夹
        //string entryPath = Path.Combine(extractionPath, Path.GetFileNameWithoutExtension(DecodeUtf8(zipFilePath)));
        //string entryDir = Path.GetDirectoryName(entryPath);
        string entryDir = extractionPath;

        if (!Directory.Exists(entryDir))
        {
            Directory.CreateDirectory(entryDir);
        }
        //Console.WriteLine(zipFilePath);
        //Console.WriteLine(extractionPath);
        // 解压
        ZipHelper.UnZip1(zipFilePath, entryDir, true);
    }




        private void ExtractRarFile(string rarFilePath, string extractionPath)
    {
        using (var archive = ArchiveFactory.Open(rarFilePath))
        {
            foreach (var entry in archive.Entries)
            {
                if (!entry.IsDirectory)
                {
                    string entryPath = Path.Combine(extractionPath, DecodeUtf8(entry.Key));
                    string entryDir = Path.GetDirectoryName(entryPath);

                    if (!Directory.Exists(entryDir))
                    {
                        Directory.CreateDirectory(entryDir);
                    }

                    using (Stream stream = entry.OpenEntryStream())
                    {
                        using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding("UTF-8")))
                        {
                            File.WriteAllText(entryPath, reader.ReadToEnd(), Encoding.GetEncoding("UTF-8"));
                        }
                    }
                }
            }
        }
    }

    private string DecodeUtf8(string input)
    {
        byte[] bytes = Encoding.Default.GetBytes(input);
        return Encoding.UTF8.GetString(bytes);
    }
}

ZipHelper.cs
封装一个不乱码的解压方法 UnZip1
来自于文章底部借鉴博客

using ICSharpCode.SharpZipLib.Checksum;
using ICSharpCode.SharpZipLib.Zip;
using System.Text;

/// <summary>
/// 压缩类
/// </summary>
public class ZipHelper
{

    /// <summary>
    /// ZIP:解压一个zip文件  这个是原始的会乱码
    /// </summary>
    /// <param name="ZipFile">需要解压的Zip文件(绝对路径)</param>
    /// <param name="TargetDirectory">解压到的目录</param>
    /// <param name="Password">解压密码</param>
    /// <param name="OverWrite">是否覆盖已存在的文件</param>
    public static void UnZip(string ZipFile, string TargetDirectory, string Password, bool OverWrite = true)
    {
        //如果解压到的目录不存在,则报错
        if (!System.IO.Directory.Exists(TargetDirectory))
        {
            throw new System.IO.FileNotFoundException("指定的目录: " + TargetDirectory + " 不存在!");
        }
        //目录结尾
        if (!TargetDirectory.EndsWith("\\")) { TargetDirectory = TargetDirectory + "\\"; }

        using (ZipInputStream zipfiles = new ZipInputStream(File.OpenRead(ZipFile)))
        {
            zipfiles.Password = Password;
            ZipEntry theEntry;
           
            while ((theEntry = zipfiles.GetNextEntry()) != null)
            {
                theEntry.IsUnicodeText = true;//解决乱码
                string directoryName = "";
                string pathToZip = "";
                pathToZip = theEntry.Name;

                if (pathToZip != "")
                    directoryName = Path.GetDirectoryName(pathToZip) + "\\";

                string fileName = Path.GetFileName(pathToZip);

                Directory.CreateDirectory(TargetDirectory + directoryName);

                if (fileName != "")
                {
                    if ((File.Exists(TargetDirectory + directoryName + fileName) && OverWrite) || (!File.Exists(TargetDirectory + directoryName + fileName)))
                    {
                        using (FileStream streamWriter = File.Create(TargetDirectory + directoryName + fileName))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = zipfiles.Read(data, 0, data.Length);

                                if (size > 0)
                                    streamWriter.Write(data, 0, size);
                                else
                                    break;
                            }
                            streamWriter.Close();
                        }
                    }
                }
            }

            zipfiles.Close();
        }
    }



    /// <summary>
    /// ZIP:解压一个zip文件   这个是GBK 修正的
    /// 最最最重要的是 SharpZipLib是1.3.3 
    /// 1.4   ZipStrings.CodePage = gbk.CodePage;
    /// 这句话可能会不兼容
    /// 
    /// https://blog.csdn.net/network_liuxu/article/details/127260948
    /// </summary>
    /// <param name="ZipFilePath">需要解压的Zip文件(绝对路径)</param>
    /// <param name="TargetDirectory">解压到的目录</param>
    /// <param name="OverWrite">是否覆盖已存在的文件</param>
    public static void UnZip1(string ZipFilePath, string TargetDirectory, bool OverWrite = true)
    {
        //如果解压到的目录不存在,则报错
        if (!System.IO.Directory.Exists(TargetDirectory))
        {
            throw new System.IO.FileNotFoundException("指定的目录: " + TargetDirectory + " 不存在!");
        }
        //目录结尾
        if (!TargetDirectory.EndsWith("\\")) { TargetDirectory = TargetDirectory + "\\"; }
        using (ZipInputStream zipfiles = new ZipInputStream(File.OpenRead(ZipFilePath)))
        {
            //zipfiles.Password = Password;
            ZipEntry theEntry;

            //最重要的三句话 告诉SharpZipLib 你的文件是什么格式的
            //SharpZipLib 它默认是UTF-8 所以有的人会乱码 改为 GBK 就可以了
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            var gbk = Encoding.GetEncoding("GBK");
            ZipStrings.CodePage = gbk.CodePage;

            while ((theEntry = zipfiles.GetNextEntry()) != null)
            {
                theEntry.IsUnicodeText = true;
                string directoryName = "";
                string pathToZip = "";
                pathToZip = theEntry.Name;

                if (pathToZip != "")
                    directoryName = Path.GetDirectoryName(pathToZip) + "\\";

                string fileName = Path.GetFileName(pathToZip);

                Directory.CreateDirectory(TargetDirectory + directoryName);

                if (fileName != "")
                {
                    if ((File.Exists(TargetDirectory + directoryName + fileName) && OverWrite) || (!File.Exists(TargetDirectory + directoryName + fileName)))
                    {
                        using (FileStream streamWriter = File.Create(TargetDirectory + directoryName + fileName))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = zipfiles.Read(data, 0, data.Length);

                                if (size > 0)
                                    streamWriter.Write(data, 0, size);
                                else
                                    break;
                            }
                            streamWriter.Close();
                        }
                    }
                }
            }

            zipfiles.Close();
        }
    }















    /// <summary>
    /// ZIP:压缩单个文件   
    /// </summary>
    /// <param name="FileToZip">需要压缩的文件(绝对路径)</param>
    /// <param name="ZipedPath">压缩后的文件路径(绝对路径)</param>
    /// <param name="ZipedFileName">压缩后的文件名称(文件名,默认 同源文件同名)</param>
    /// <param name="CompressionLevel">压缩等级(0 无 - 9 最高,默认 5)</param>
    /// <param name="BlockSize">缓存大小(每次写入文件大小,默认 2048)</param>
    /// <param name="IsEncrypt">是否加密(默认 加密)</param>
    public static void ZipFile(string FileToZip, string ZipedPath, string ZipedFileName = "", int CompressionLevel = 5, int BlockSize = 2048, bool IsEncrypt = true)
    {
        //如果文件没有找到,则报错
        if (!System.IO.File.Exists(FileToZip))
        {
            throw new System.IO.FileNotFoundException("指定要压缩的文件: " + FileToZip + " 不存在!");
        }

        //文件名称(默认同源文件名称相同)
        string ZipFileName = string.IsNullOrEmpty(ZipedFileName) ? ZipedPath + "\\" + new FileInfo(FileToZip).Name.Substring(0, new FileInfo(FileToZip).Name.LastIndexOf('.')) + ".zip" : ZipedPath + "\\" + ZipedFileName + ".zip";

        using (System.IO.FileStream ZipFile = System.IO.File.Create(ZipFileName))
        {
            using (ZipOutputStream ZipStream = new ZipOutputStream(ZipFile))
            {
                using (System.IO.FileStream StreamToZip = new System.IO.FileStream(FileToZip, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    string fileName = FileToZip.Substring(FileToZip.LastIndexOf("\\") + 1);

                    ZipEntry ZipEntry = new ZipEntry(fileName);
                    ZipEntry.IsUnicodeText = true;//解决乱码
                    if (IsEncrypt)
                    {
                        //压缩文件加密
                        ZipStream.Password = "123";
                    }

                    ZipStream.PutNextEntry(ZipEntry);

                    //设置压缩级别
                    ZipStream.SetLevel(CompressionLevel);

                    //缓存大小
                    byte[] buffer = new byte[BlockSize];

                    int sizeRead = 0;

                    try
                    {
                        do
                        {
                            sizeRead = StreamToZip.Read(buffer, 0, buffer.Length);
                            ZipStream.Write(buffer, 0, sizeRead);
                        }
                        while (sizeRead > 0);
                    }
                    catch (System.Exception ex)
                    {
                        throw ex;
                    }

                    StreamToZip.Close();
                }

                ZipStream.Finish();
                ZipStream.Close();
            }

            ZipFile.Close();
        }
    }


    /// <summary>
    /// ZIP:压缩文件夹
    /// </summary>
    /// <param name="DirectoryToZip">需要压缩的文件夹(绝对路径)</param>
    /// <param name="ZipedPath">压缩后的文件路径(绝对路径)</param>
    /// <param name="ZipedFileName">压缩后的文件名称(文件名,默认 同源文件夹同名)</param>
    /// <param name="IsEncrypt">是否加密(默认 加密)</param>
    public static void ZipDirectory(string DirectoryToZip, string ZipedPath, string ZipedFileName = "", bool IsEncrypt = true)
    {
        //如果目录不存在,则报错
        if (!System.IO.Directory.Exists(DirectoryToZip))
        {
            throw new System.IO.FileNotFoundException("指定的目录: " + DirectoryToZip + " 不存在!");
        }

        //文件名称(默认同源文件名称相同)
        string ZipFileName = string.IsNullOrEmpty(ZipedFileName) ? ZipedPath + "\\" + new DirectoryInfo(DirectoryToZip).Name + ".zip" : ZipedPath + "\\" + ZipedFileName + ".zip";

        using (System.IO.FileStream ZipFile = System.IO.File.Create(ZipFileName))
        {
            using (ZipOutputStream s = new ZipOutputStream(ZipFile))
            {
                if (IsEncrypt)
                {
                    //压缩文件加密
                    s.Password = "123";
                }
                ZipSetp(DirectoryToZip, s, "");
            }
        }
    }
    /// <summary>
    /// 递归遍历目录
    /// </summary>
    private static void ZipSetp(string strDirectory, ZipOutputStream s, string parentPath)
    {
        if (strDirectory[strDirectory.Length - 1] != Path.DirectorySeparatorChar)
        {
            strDirectory += Path.DirectorySeparatorChar;
        }
        Crc32 crc = new Crc32();

        string[] filenames = Directory.GetFileSystemEntries(strDirectory);

        foreach (string file in filenames)// 遍历所有的文件和目录
        {

            if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
            {
                string pPath = parentPath;
                pPath += file.Substring(file.LastIndexOf("\\") + 1);
                pPath += "\\";
                ZipSetp(file, s, pPath);
            }

            else // 否则直接压缩文件
            {
                //打开压缩文件
                using (FileStream fs = File.OpenRead(file))
                {

                    byte[] buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, buffer.Length);

                    string fileName = parentPath + file.Substring(file.LastIndexOf("\\") + 1);
                    ZipEntry entry = new ZipEntry(fileName);
                    entry.IsUnicodeText = true;//解决乱码
                    entry.DateTime = DateTime.Now;
                    entry.Size = fs.Length;

                    fs.Close();

                    crc.Reset();
                    crc.Update(buffer);

                    entry.Crc = crc.Value;
                    s.PutNextEntry(entry);

                    s.Write(buffer, 0, buffer.Length);
                }
            }
        }
    }
}


main.cs

选一个文件夹,直接递归开始

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
using System.Text;
using static ICSharpCode.SharpZipLib.Zip.FastZip;


namespace _0_分卷压缩;

internal class Main2
{
    static void Main()
    {
        string sourceDirectory = @"H:\【7】工具脚本\【6】2021-04-28  1天  孟涛工具\新建文件夹";



        string rootPath = sourceDirectory;
        var archiveManager = new ArchiveManager(rootPath);
        archiveManager.ProcessArchives();

        Console.WriteLine("解压缩完成!");

    }
}



借鉴:https://blog.csdn.net/qq_39273807/article/details/124065744

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值