网上寻找压缩文件和解压文件的方法,总是会有奇怪的错误,比如创建了压缩文件,然而压缩文件只有大小而没有内容,又或者解压方法与压缩方法不配套,解压时抛出“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
换了个解压方法,然而我突然找不到来源了。。。 之前的解压方法在安卓上有较大概率失败,什么都不发生,现在更新的方法,在安卓下也能如期运行。