欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

文件解压缩

程序员文章站 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();
    }
}
相关标签: 解压缩 C#