需求:解压一个目录下所有压缩文件到所在目录
时间:2023-07-31
问题:zip解压乱码,rar不会(巨硬nb)
原因:GBK编码问题
库 | 版本 |
---|---|
ICSharpCode.SharpZipLib | 0.85 |
SharpCompress | 0.32 |
SharpZipLib | 1.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