文件解压缩
程序员文章站
2022-05-15 11:26:30
...
最近需要一个解压缩的需求,因为文件较多,所以希望能看到正在解压的文件名,于是需要个委托来返回文件名。
首先我们先定义一个解压缩的帮助类,这里我用了DotNetZip.dll。
using Ionic.Zlib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XXX
{
public class GZipHelper
{
public delegate void ProgressDelegate(string sMessage);
public static byte[] Compress(byte[] data)
{
if (data == null)
{
return null;
}
MemoryStream stream = new MemoryStream();
using (GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress, CompressionLevel.BestCompression))
{
gZipStream.Write(data, 0, data.Length);
gZipStream.Close();
}
return stream.ToArray();
}
public static byte[] Decompress(byte[] data)
{
if (data == null)
{
return null;
}
MemoryStream stream = new MemoryStream(data);
MemoryStream decompress_stream = new MemoryStream(1024 * 5);
using (GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress, true))
{
int count = 0;
do
{
byte[] byteBuffer = new byte[512];
count = gZipStream.Read(byteBuffer, 0, byteBuffer.Length);
decompress_stream.Write(byteBuffer, 0, count);
} while (count > 0);
return decompress_stream.ToArray();
}
}
/// <summary>
/// 压缩文件
/// </summary>
/// <param name="sourceFile">源文件</param>
/// <param name="destinationFile">目标文件</param>
public static void CompressFile(string sourceFile, string destinationFile)
{
if (!File.Exists(sourceFile)) //判断文件是否存在
throw new FileNotFoundException();
//if (!File.Exists(destinationFile)) //判断目标文件文件是否存在
// File.Delete(destinationFile);
//创建文件流和字节数组
byte[] buffer = null;
FileStream sourceStream = null;
FileStream destinationStream = null;
GZipStream compressedStream = null;
try
{
sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
buffer = new byte[sourceStream.Length];
//把文件流存放到字节数组中
int checkCounter = sourceStream.Read(buffer, 0, buffer.Length);
if (checkCounter != buffer.Length)
{
throw new ApplicationException();
}
destinationStream = new FileStream(destinationFile, FileMode.OpenOrCreate, FileAccess.Write);
//创建GzipStream实例,写入压缩的文件流
compressedStream = new GZipStream(destinationStream, CompressionMode.Compress, true);
compressedStream.Write(buffer, 0, buffer.Length);
}
finally
{
// Make sure we allways close all streams
if (sourceStream != null)
{ sourceStream.Close(); }
if (compressedStream != null)
{ compressedStream.Close(); }
if (destinationStream != null)
{ destinationStream.Close(); }
}
}
/// <summary>
/// 解压文件
/// </summary>
/// <param name="sourceFile">源文件</param>
/// <param name="destinationFile">目标文件</param>
public static void DecompressFile(string sourceFile, string destinationFile)
{
if (!File.Exists(sourceFile))
{
throw new FileNotFoundException();
}
FileStream stream = null;
FileStream stream2 = null;
GZipStream stream3 = null;
byte[] buffer = null;
try
{
stream = new FileStream(sourceFile, FileMode.Open);
stream3 = new GZipStream(stream, CompressionMode.Decompress, true);
buffer = new byte[4];
int num = ((int)stream.Length) - 4;
stream.Position = num;
stream.Read(buffer, 0, 4);
stream.Position = 0L;
byte[] buffer2 = new byte[BitConverter.ToInt32(buffer, 0) + 100];
int offset = 0;
int count = 0;
while (true)
{
int num5 = stream3.Read(buffer2, offset, 100);
if (num5 == 0)
{
break;
}
offset += num5;
count += num5;
}
stream2 = new FileStream(destinationFile, FileMode.Create);
stream2.Write(buffer2, 0, count);
stream2.Flush();
}
finally
{
if (stream != null)
{
stream.Close();
}
if (stream3 != null)
{
stream3.Close();
}
if (stream2 != null)
{
stream2.Close();
}
}
}
private static void CompressFile(string sDir, string sRelativePath, GZipStream zipStream)
{
//Compress file name
char[] chars = sRelativePath.ToCharArray();
zipStream.Write(BitConverter.GetBytes(chars.Length), 0, sizeof(int));
foreach (char c in chars)
zipStream.Write(BitConverter.GetBytes(c), 0, sizeof(char));
//Compress file content
byte[] bytes = File.ReadAllBytes(Path.Combine(sDir, sRelativePath));
zipStream.Write(BitConverter.GetBytes(bytes.Length), 0, sizeof(int));
zipStream.Write(bytes, 0, bytes.Length);
}
private static bool DecompressFile(string sDir, GZipStream zipStream, ProgressDelegate progress)
{
//Decompress file name
byte[] bytes = new byte[sizeof(int)];
int Readed = zipStream.Read(bytes, 0, sizeof(int));
if (Readed < sizeof(int))
return false;
int iNameLen = BitConverter.ToInt32(bytes, 0);
bytes = new byte[sizeof(char)];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iNameLen; i++)
{
zipStream.Read(bytes, 0, sizeof(char));
char c = BitConverter.ToChar(bytes, 0);
sb.Append(c);
}
string sFileName = sb.ToString();
if (progress != null)
progress(sFileName);
//Decompress file content
bytes = new byte[sizeof(int)];
zipStream.Read(bytes, 0, sizeof(int));
int iFileLen = BitConverter.ToInt32(bytes, 0);
bytes = new byte[iFileLen];
zipStream.Read(bytes, 0, bytes.Length);
string sFilePath = Path.Combine(sDir, sFileName);
string sFinalDir = Path.GetDirectoryName(sFilePath);
if (!Directory.Exists(sFinalDir))
Directory.CreateDirectory(sFinalDir);
using (FileStream outFile = new FileStream(sFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
outFile.Write(bytes, 0, iFileLen);
return true;
}
/// <summary>
/// 压缩文件夹
/// </summary>
/// <param name="sInDir">源文件夹</param>
/// <param name="sOutFile">目标文件</param>
public static void CompressDirectory(string sInDir, string sOutFile, ProgressDelegate progress)
{
string[] sFiles = Directory.GetFiles(sInDir, "*.*", SearchOption.AllDirectories);
int iDirLen = sInDir[sInDir.Length - 1] == Path.DirectorySeparatorChar ? sInDir.Length : sInDir.Length + 1;
using (FileStream outFile = new FileStream(sOutFile, FileMode.Create, FileAccess.Write, FileShare.None))
using (GZipStream str = new GZipStream(outFile, CompressionMode.Compress))
foreach (string sFilePath in sFiles)
{
string sRelativePath = sFilePath.Substring(iDirLen);
if (progress != null)
progress(sRelativePath);
CompressFile(sInDir, sRelativePath, str);
}
}
/// <summary>
/// 解压文件夹
/// </summary>
/// <param name="sCompressedFile">源文件</param>
/// <param name="sDir">目标文件夹</param>
public static void DecompressToDirectory(string sCompressedFile, string sDir, ProgressDelegate progress)
{
using (FileStream inFile = new FileStream(sCompressedFile, FileMode.Open, FileAccess.Read, FileShare.None))
using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true))
while (DecompressFile(sDir, zipStream, progress)) ;
}
}
}
导入
//解压版
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == true)
{
ImportWindow import = new ImportWindow();
DateTime dt = DateTime.Now;
import.Show();
EcgProject prjObj = null;
await TaskAsyncHelper.RunAsync(new Action(() =>
{
string userWorkFolderPath =“目标文件地址”;
GZipHelper.DecompressToDirectory(ofd.FileName, userWorkFolderPath, (filename) =>
{
Application.Current.Dispatcher.BeginInvoke(new Action(() => { import.LabelContent = string.Format("正在导入{0}", filename); }));
});
}), new Action(() =>
{
import.Close();
MessageBox.Show($"导入项目成功!{DateTime.Now - dt}");
}));
}
导出
//压缩版
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == true)
{
DateTime dt = DateTime.Now;
ExportWindow import = new ExportWindow();
import.Show();
await TaskAsyncHelper.RunAsync(new Action(() => {
GZipHelper.CompressDirectory(“源文件位置”, sfd.FileName, (filename) => {
Application.Current.Dispatcher.BeginInvoke(new Action(() => { import.LabelContent = string.Format("正在导出{0}", filename); }));
});
}), new Action(() =>
{
import.Close();
MessageBoxHelper.ShowMessage($"Export OK!{DateTime.Now - dt}", $"导出项目成功!{DateTime.Now - dt}", (LangType)SysInfoModel.SysInfo.LangType);
}));
}
自定义的ExportWindow与ImportWindow就不给出了。TaskAsyncHelper.RunAsync的方法如下
public static class TaskAsyncHelper
{
/// <summary>
/// 将一个方法function异步运行,在执行完毕时执行回调callback
/// </summary>
/// <param name="function">异步方法,该方法没有参数,返回类型必须是void</param>
/// <param name="callback">异步方法执行完毕时执行的回调方法,该方法没有参数,返回类型必须是void</param>
public static async Task RunAsync(Action function, Action callback)
{
Func<Task> taskFunc = () =>
{
return Task.Run(function);
};
await taskFunc();
if (callback != null)
callback();
}
}
上一篇: 云计算不是虚拟化 提防网络成瓶颈
下一篇: 九九乘法表 批处理版