使用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;

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

    /// 
    /// 生成压缩文件(单个文件压缩,可以用来测试一下方法是否可行)
    /// 
    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();
            }
        }
    }

    /// 
    /// 递归压缩目录(文件夹)
    /// 
    /// 
    /// 
    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 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();
            }
        }
    }

    /// 
    /// 获取这个文件相对于指定目录的相对路径
    /// 
    /// 
    /// 
    /// 
    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;
    }

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

    /// 
    /// 得到指定文件夹下的所有文件名(绝对路径)
    /// 
    /// 
    /// 
    public static List 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);
    }

    /// 
    /// 递归得到指定文件夹下所有文件名(绝对路径)
    /// 
    /// 
    /// 
    public static List GetAllFilenamesFromFolder(DirectoryInfo root)
    {
        List filenames = new List();
        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;
    }

    /// 
    /// 递归得到文件夹大小(单位为:b)
    /// 
    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;
    }

    

    /// 
    /// 异目录解压
    /// 
    /// 
    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();
        }
    }

    /// 
    /// 同目录解压
    /// 
    /// 解压目录
    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();
        }
    }

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

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

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

你可能感兴趣的:(发现并解决了的错误)