使用ICSharpZipLib进行压缩和解压(整理)

网上寻找压缩文件和解压文件的方法,总是会有奇怪的错误,比如创建了压缩文件,然而压缩文件只有大小而没有内容,又或者解压方法与压缩方法不配套,解压时抛出“Could not find a part of the path”的异常。

终于在网上找到优秀的压缩方法,和另一个解压方法,整理到一起后,放到这里,给自己以后使用,也给有需求的人使用。

 

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class ZipUtility
{
    public static ZipUtility Instance
    {
        get
        {
            if (null == m_instance)
            {
                m_instance = new ZipUtility();
            }
            return m_instance;
        }
    }
    private static ZipUtility m_instance;

    private ZipUtility() { }

    //默认的压缩质量
    private int m_compressLevel = 6;

    /// <summary>
    /// 设置压缩质量
    /// </summary>
    public static void SetCompressLevel(int level)
    {
        Instance.m_compressLevel = level;
    }

    /// <summary>
    /// 生成压缩文件(单个文件压缩,可以用来测试一下方法是否可行)
    /// </summary>
    public static void GenerateZipFile(string fileToZip, string zipedFilename)
    {
        using (FileStream fsOut = File.Create(zipedFilename))
        {
            using (ZipOutputStream zipStream = new ZipOutputStream(fsOut))
            {
                zipStream.SetLevel(Instance.m_compressLevel);
                FileInfo fileinfo = new FileInfo(fileToZip);
                string entryName = Path.GetFileName(fileToZip);
                ZipEntry entry = new ZipEntry(entryName);
                entry.DateTime = fileinfo.LastWriteTime;
                entry.Size = fileinfo.Length;
                zipStream.PutNextEntry(entry);
                byte[] buffer = new byte[4096];
                using (FileStream reader = File.OpenRead(fileToZip))
                {
                    StreamUtils.Copy(reader, zipStream, buffer);
                }
                zipStream.CloseEntry();
                zipStream.IsStreamOwner = false;
                zipStream.Finish();
                zipStream.Close();
            }
        }
    }

    /// <summary>
    /// 递归压缩目录(文件夹)
    /// </summary>
    /// <param name="folderToZip"></param>
    /// <param name="zipedFilename"></param>
    public static void GenerateZipFileFromFolder(string folderToZip, string zipedFilename)
    {
        if (!Directory.Exists(folderToZip))
        {
            //要求文件夹必须存在,不必创建,否则会压出一个空文件
            throw new DirectoryNotFoundException(string.Format("不存在的目录: {0}", folderToZip));
        }
        using (FileStream fsOut = File.Create(zipedFilename))
        {
            using (ZipOutputStream zipStream = new ZipOutputStream(fsOut))
            {
                zipStream.SetLevel(Instance.m_compressLevel);
                //对应目录下所有的文件名
                List<string> filenames = GetAllFilenamesFromFolder(folderToZip);
                int filenamesCount = filenames.Count;
                //将该文件夹下所有文件进行压缩
                for (int i = 0; i < filenamesCount; ++i)
                {
                    string filename = filenames[i];
                    if (filename.Equals(zipedFilename))
                    {
                        //如果同文件夹压缩,则在该文件夹下刚刚创建了这个文件
                        //因此跳过这个文件
                        continue;
                    }
                    FileInfo fileinfo = new FileInfo(filename);
                    //获取这个文件的相对于目录的路径,这是生成压缩文件中,文件夹的关 
                    //键"root\\child\\grandson"
                    string relativeName = GetRelativePath(folderToZip, filename);
                    ZipEntry entry = new ZipEntry(relativeName);
                    entry.DateTime = fileinfo.LastWriteTime;
                    entry.Size = fileinfo.Length;

                    //将这个Entry放入zipStream中,对其进行操作
                    zipStream.PutNextEntry(entry);
                    byte[] buffer = new byte[entry.Size];
                    using (FileStream reader = File.OpenRead(filename))
                    {
                        StreamUtils.Copy(reader, zipStream, buffer);
                    }
                    zipStream.CloseEntry();
                }
                zipStream.IsStreamOwner = false;
                zipStream.Finish();
                zipStream.Close();
            }
        }
    }

    /// <summary>
    /// 获取这个文件相对于指定目录的相对路径
    /// </summary>
    /// <param name="rootFolder"></param>
    /// <param name="filename"></param>
    /// <returns></returns>
    public static string GetRelativePath(string rootFolder, string filename)
    {
        //如果指定目录的长度比文件的绝对路径还长,则不存在的
        if (filename.Length < rootFolder.Length)
        {
            throw new Exception(string.Format("filename:{0} is shorter than rootFolder:{1}", filename, rootFolder));
        }
        //如果文件的绝对路径不是以指定目录开始,则说明这个文件不在这个文件夹下
        if (!filename.StartsWith(rootFolder))
        {
            throw new Exception(string.Format("file:{0} is not in this folder:{1}", filename, rootFolder));
        }
        string relative = filename.Remove(0, rootFolder.Length);
        return relative;
    }

    /// <summary>
    /// 将反斜杠改写为斜杠,这是为了保证文件绝对路径的同意,否则GetRelativePath将判断失误
    /// </summary>
    /// <param name="originalPath"></param>
    /// <returns></returns>
    public static string TranslateBackSlash(string originalPath)
    {
        originalPath = originalPath.Replace(@"\", "/");
        return originalPath;
    }

    /// <summary>
    /// 得到指定文件夹下的所有文件名(绝对路径)
    /// </summary>
    /// <param name="rootFolder"></param>
    /// <returns></returns>
    public static List<string> GetAllFilenamesFromFolder(string rootFolder)
    {
        if (!Directory.Exists(rootFolder))
        {
            throw new DirectoryNotFoundException(string.Format("Directory--{0} is not exist", rootFolder));
        }
        DirectoryInfo root = new DirectoryInfo(rootFolder);
        return GetAllFilenamesFromFolder(root);
    }

    /// <summary>
    /// 递归得到指定文件夹下所有文件名(绝对路径)
    /// </summary>
    /// <param name="root"></param>
    /// <returns></returns>
    public static List<string> GetAllFilenamesFromFolder(DirectoryInfo root)
    {
        List<string> filenames = new List<string>();
        DirectoryInfo[] folders = root.GetDirectories();
        if (folders.Length != 0)
        {
            for (int i = 0; i < folders.Length; ++i)
            {
                DirectoryInfo folder = folders[i];
                //递归添加绝对路径
                filenames.AddRange(GetAllFilenamesFromFolder(folder));
            }
        }
        FileInfo[] files = root.GetFiles();
        if (files.Length != 0)
        {
            for (int i = 0; i < files.Length; ++i)
            {
                FileInfo fileinfo = files[i];
                filenames.Add(TranslateBackSlash(fileinfo.FullName));
            }
        }
        return filenames;
    }

    /// <summary>
    /// 递归得到文件夹大小(单位为:b)
    /// </summary>
    public static long GetFolderSize(string folderPath)
    {
        if (!Directory.Exists(folderPath))
        {
            throw new DirectoryNotFoundException(string.Format("Directory--{0} is not exist", folderPath));
        }
        long size = 0;
        DirectoryInfo root = new DirectoryInfo(folderPath);
        DirectoryInfo[] childFolders = root.GetDirectories();
        if (childFolders.Length != 0)
        {
            for (int i = 0; i < childFolders.Length; ++i)
            {
                string childFolderPath = childFolders[i].FullName;
                //递归
                size += GetFolderSize(childFolderPath);
            }
        }
        FileInfo[] fileInfos = root.GetFiles();
        if (fileInfos.Length != 0)
        {
            for (int i = 0; i < fileInfos.Length; ++i)
            {
                FileInfo file = fileInfos[i];
                size += file.Length;
            }
        }
        return size;
    }

    

    /// <summary>
    /// 异目录解压
    /// </summary>
    /// <param name="zipFile"></param>
    public static void UnzipFile(string zipFile, string savePath)
    {
        string saveFolder = Path.GetDirectoryName(savePath);
        if (!Directory.Exists(saveFolder))
        {
            Directory.CreateDirectory(saveFolder);
        }
        if (!saveFolder.EndsWith(@"\"))
        {
            saveFolder += @"\";
        }
        using (ZipInputStream zipFiles = new ZipInputStream(File.OpenRead(zipFile)))
        {
            ZipEntry entry;
            while ((entry = zipFiles.GetNextEntry()) != null)
            {
                string directory = string.Empty;
                string pathToZip = entry.Name;
                if (!string.IsNullOrEmpty(pathToZip))
                {
                    directory = Path.GetDirectoryName(pathToZip) + @"\";
                }
                string filename = Path.GetFileName(pathToZip);

                if (!Directory.Exists(saveFolder + directory))
                {
                    Directory.CreateDirectory(saveFolder + directory);
                }

                if (!string.IsNullOrEmpty(filename))
                {
                    if (File.Exists(saveFolder + directory + filename))
                    {
                        File.Delete(saveFolder + directory + filename);
                    }
                    using (FileStream writer = File.Create(saveFolder + directory + filename))
                    {
                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
                            size = zipFiles.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                writer.Write(data, 0, size);
                            }
                            else
                            {
                                break;
                            }
                        }
                        writer.Close();
                    }

                }
            }
            zipFiles.Close();
        }
    }

    /// <summary>
    /// 同目录解压
    /// </summary>
    /// <param name="zipFile">解压目录</param>
    public static void UnzipFile(string path)
    {
        int doneCount = 0;
        int indicatorStep = 1;

        ZipConstants.DefaultCodePage = System.Text.Encoding.UTF8.CodePage;
        Debug.Log("Path = " + path);
        //根目录路径
        string dirPath = path.Substring(0, path.LastIndexOf('/'));
        //ZipEntry: 文件条目,就是该目录下所有的文件列表(也就是所有文件的路径)
        ZipEntry zip = null;
        //输入的所有的文件流都是存储在这里面的
        ZipInputStream zipInStream = null;
        //读取文件流到zipInStream
        zipInStream = new ZipInputStream(File.OpenRead(path));
        //循环读取Zip目录下的所有文件
        while ((zip = zipInStream.GetNextEntry()) != null)
        {
            //Debug.Log("name = " + zip.Name + " zipStream " + zipInStream);
            UnzipFile(zip, zipInStream, dirPath);
            doneCount++;
            if (doneCount % indicatorStep == 0)
            {
                Thread.Sleep(20);
            }
        }
        try
        {
            zipInStream.Close();
        }
        catch (Exception e)
        {
            Debug.Log("UnZip Error");
            Loom.QueueOnMainThread((needless) =>
            {
                APPGlobals.Instance.UIPanelManager.OpenPopMsg(string.Format("UnZip Error: {0}", e.Message));
            }, null);
            throw e;
        }
    }

    private static void UnzipFile(ZipEntry zip, ZipInputStream zipInStream, string dirPath)
    {
        try
        {
            if (!string.IsNullOrEmpty(zip.Name))
            {
                string filePath = dirPath;
                filePath += ("/" + zip.Name);

                //如果这是一个新的文件路径,这里需要创建这个文件路径
                if (IsDirectory(filePath))
                {
                    Debug.Log("Create file path " + filePath);
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }
                }
                else
                {
                    FileStream fs = null;
                    //当前文件夹下有该文件,删除,重新创建
                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }
                    string root = Path.GetDirectoryName(filePath);
                    if (!Directory.Exists(root))
                    {
                        Directory.CreateDirectory(root);
                    }
                    fs = File.Create(filePath);
                    int size = 2048;
                    byte[] data = new byte[2048];
                    //每次读取2M 直到把这个文件内容读完
                    while (true)
                    {
                        size = zipInStream.Read(data, 0, data.Length);
                        if (size > 0)
                        {
                            fs.Write(data, 0, size);
                        }
                        else
                        {
                            break;
                        }
                    }
                    fs.Close();
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogErrorFormat("{0}     ||{1}", e.Message, e.StackTrace);
            throw new Exception();
        }
    }

    /// <summary>
    /// 创建是否是目录文件
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    private static bool IsDirectory(string path)
    {
        if (path[path.Length - 1] == '/')
        {
            return true;
        }
        return false;
    }
}

压缩方法转自:http://www.cnblogs.com/sparkdev/p/6826948.html

换了个解压方法,然而我突然找不到来源了。。。 之前的解压方法在安卓上有较大概率失败,什么都不发生,现在更新的方法,在安卓下也能如期运行。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
zip压缩DLL 可以使用程序自己来控制 压缩,解压. c#使用代码如下: /// /// 压缩解压文件 /// public class ZipClass { /// /// 所有文件缓存 /// List files = new List(); /// /// 所有空目录缓存 /// List paths = new List(); /// /// 压缩单个文件 /// /// 要压缩的文件 /// 压缩后的文件全名 /// 压缩程度,范围0-9,数值越大,压缩程序越高 /// 分块大小 public void ZipFile(string fileToZip, string zipedFile, int compressionLevel, int blockSize) { if (!System.IO.File.Exists(fileToZip))//如果文件没有找到,则报错 { throw new FileNotFoundException("The specified file " + fileToZip + " could not be found. Zipping aborderd"); } FileStream streamToZip = new FileStream(fileToZip, FileMode.Open, FileAccess.Read); FileStream zipFile = File.Create(zipedFile); ZipOutputStream zipStream = new ZipOutputStream(zipFile); ZipEntry zipEntry = new ZipEntry(fileToZip); zipStream.PutNextEntry(zipEntry); zipStream.SetLevel(compressionLevel); byte[] buffer = new byte[blockSize]; int size = streamToZip.Read(buffer, 0, buffer.Length); zipStream.Write(buffer, 0, size); try { while (size < streamToZip.Length) { int sizeRead = streamToZip.Read(buffer, 0, buffer.Length); zipStream.Write(buffer, 0, sizeRead); size += sizeRead; } } catch (Exception ex) { GC.Collect(); throw ex; } zipStream.Finish(); zipStream.Close(); streamToZip.Close(); GC.Collect(); } /// /// 压缩目录(包括子目录及所有文件) /// /// 要压缩的根目录 /// 保存路径 /// 压缩程度,范围0-9,数值越大,压缩程序越高 public void ZipFileFromDirectory(string rootPath, string destinationPath, int compressLevel) { GetAllDirectories(rootPath); /* while (rootPath.LastIndexOf("\\") + 1 == rootPath.Length)//检查路径是否以"\"结尾 { rootPath = rootPath.Substring(0, rootPath.Length - 1);//如果是则去掉末尾的"\" } */ //string rootMark = rootPath.Substring(0, rootPath.LastIndexOf("\\") + 1);//得到当前路径的位置,以备压缩时将所压缩内容转变成相对路径。 string rootMark = rootPath + "\\";//得到当前路径的位置,以备压缩时将所压缩内容转变成相对路径。 Crc32 crc = new Crc32(); ZipOutputStream outPutStream = new ZipOutputStream(File.Create(destinationPath)); outPutStream.SetLevel(compressLevel); // 0 - store only to 9 - means best compression foreach (string file in files) { FileStream fileStream = File.OpenRead(file);//打开压缩文件 byte[] buffer = new byte[fileStream.Length]; fileStream.Read(buffer, 0, buffer.Length); ZipEntry entry = new ZipEntry(file.Replace(rootMark, string.Empty)); entry.DateTime = DateTime.Now; // set Size and the crc, because the information // about the size and crc should be stored in the header // if it is not set it is automatically written in the footer. // (in this case size == crc == -1 in the header) // Some ZIP programs have problems with zip files that don't store // the size and crc in the header. entry.Size = fileStream.Length; fileStream.Close(); crc.Reset(); crc.Update(buffer); entry.Crc = crc.Value; outPutStream.PutNextEntry(entry); outPutStream.Write(buffer, 0, buffer.Length); } this.files.Clear(); foreach (string emptyPath in paths) { ZipEntry entry = new ZipEntry(emptyPath.Replace(rootMark, string.Empty) + "/"); outPutStream.PutNextEntry(entry); } this.paths.Clear(); outPutStream.Finish(); outPutStream.Close(); GC.Collect(); } /// /// 取得目录下所有文件及文件夹,分别存入files及paths /// /// 根目录 private void GetAllDirectories(string rootPath) { string[] subPaths = Directory.GetDirectories(rootPath);//得到所有子目录 foreach (string path in subPaths) { GetAllDirectories(path);//对每一个字目录做与根目录相同的操作:即找到子目录并将当前目录的文件名存入List } string[] files = Directory.GetFiles(rootPath); foreach (string file in files) { this.files.Add(file);//将当前目录中的所有文件全名存入文件List } if (subPaths.Length == files.Length && files.Length == 0)//如果是空目录 { this.paths.Add(rootPath);//记录空目录 } } /// /// 解压缩文件(压缩文件中含有子目录) /// /// 待解压缩的文件路径 /// 解压缩到指定目录 /// 解压后的文件列表 public List UnZip(string zipfilepath, string unzippath) { //解压出来的文件列表 List unzipFiles = new List(); //检查输出目录是否以“\\”结尾 if (unzippath.EndsWith("\\") == false || unzippath.EndsWith(":\\") == false) { unzippath += "\\"; } ZipInputStream s = new ZipInputStream(File.OpenRead(zipfilepath)); ZipEntry theEntry; while ((theEntry = s.GetNextEntry()) != null) { string directoryName = Path.GetDirectoryName(unzippath); string fileName = Path.GetFileName(theEntry.Name); //生成解压目录【用户解压到硬盘根目录时,不需要创建】 if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } if (fileName != String.Empty) { //如果文件的压缩后大小为0那么说明这个文件是空的,因此不需要进行读出写入 if (theEntry.CompressedSize == 0) break; //解压文件到指定的目录 directoryName = Path.GetDirectoryName(unzippath + theEntry.Name); //建立下面的目录和子目录 Directory.CreateDirectory(directoryName); //记录导出的文件 unzipFiles.Add(unzippath + theEntry.Name); FileStream streamWriter = File.Create(unzippath + theEntry.Name); int size = 2048; byte[] data = new byte[2048]; while (true) { size = s.Read(data, 0, data.Length); if (size > 0) { streamWriter.Write(data, 0, size); } else { break; } } streamWriter.Close(); } } s.Close(); GC.Collect(); return unzipFiles; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值