在Unity中对含有中文的Zip压缩文件解压真的是挺坑的一件事情。普通C#工程,只要目标框架在.NET Framework 4.5(含)以上版本,只要一行代码就能搞定的事:
ZipFile.ExtractToDirectory("zip目录", "解压目录");
unity老旧的3.5让它变得难搞,因为没了c#自带解压zip功能,只好转而求助第三方库,ICSharpCode.SharpZipLib.dll就是个用来解压zip文件的库,但是你用了就会发现一般的用法确实能够解压,但是中文部分全都乱码了。解决这个问题,网上有很多改法,但是我试了好多,有些直接就不管用,有些没说使用的dll版本号,下载下来后发现压根就没有要修改的相关属性,还有些改法,用是能用,能解压出来,也不乱码了,但是每个中文文件结果都莫名的加了好多无用的字节,导致还是不能使用,好烦。
话不多少,我直接贴上代码和dll下载地址,能正常解压,不乱码,也没结尾多加无用字节。
public abstract class UnzipCallback
{
///
/// 解压单个文件或文件夹前执行的回调
///
///
/// 如果返回true,则压缩文件或文件夹,反之则不压缩文件或文件夹
public virtual bool OnPreUnzip(ZipEntry _entry)
{
return true;
}
///
/// 解压单个文件或文件夹后执行的回调
///
///
public virtual void OnPostUnzip(ZipEntry _entry) { }
///
/// 解压执行完毕后的回调
///
/// true表示解压成功,false表示解压失败
public virtual void OnFinished(bool _result) { }
}
/// 解压Zip包
///
/// Zip包的文件路径名
/// 解压输出路径
/// 解压密码
/// UnzipCallback对象,负责回调
///
public static bool UnzipFile(string _filePathName, string _outputPath, string _password = null, UnzipCallback _unzipCallback = null)
{
if (string.IsNullOrEmpty(_filePathName) || string.IsNullOrEmpty(_outputPath))
{
if (null != _unzipCallback)
_unzipCallback.OnFinished(false);
return false;
}
try
{
return UnzipFile(File.OpenRead(_filePathName), _outputPath, _password, _unzipCallback);
}
catch (System.Exception _e)
{
Debug.LogError("[ZipUtility.UnzipFile]: " + _e.ToString());
if (null != _unzipCallback)
_unzipCallback.OnFinished(false);
return false;
}
}
///
/// 解压Zip包
///
/// Zip包字节数组
/// 解压输出路径
/// 解压密码
/// UnzipCallback对象,负责回调
///
public static bool UnzipFile(byte[] _fileBytes, string _outputPath, string _password = null, UnzipCallback _unzipCallback = null)
{
if ((null == _fileBytes) || string.IsNullOrEmpty(_outputPath))
{
if (null != _unzipCallback)
_unzipCallback.OnFinished(false);
return false;
}
bool result = UnzipFile(new MemoryStream(_fileBytes), _outputPath, _password, _unzipCallback);
if (!result)
{
if (null != _unzipCallback)
_unzipCallback.OnFinished(false);
}
return result;
}
///
/// 解压Zip包
///
/// Zip包输入流
/// 解压输出路径
/// 解压密码
/// UnzipCallback对象,负责回调
///
public static bool UnzipFile(Stream _inputStream, string _outputPath, string _password = null, UnzipCallback _unzipCallback = null)
{
if ((null == _inputStream) || string.IsNullOrEmpty(_outputPath))
{
if (null != _unzipCallback)
_unzipCallback.OnFinished(false);
return false;
}
// 创建文件目录
if (!Directory.Exists(_outputPath))
Directory.CreateDirectory(_outputPath);
// 解压Zip包
ZipEntry entry = null;
Encoding gbk = Encoding.GetEncoding("gbk");
ICSharpCode.SharpZipLib.Zip.ZipConstants.DefaultCodePage = gbk.CodePage;
using (ZipInputStream zipInputStream = new ZipInputStream(_inputStream))
{
if (!string.IsNullOrEmpty(_password))
zipInputStream.Password = _password;
while (null != (entry = zipInputStream.GetNextEntry()))
{
if (null == entry ||string.IsNullOrEmpty(entry.Name))
continue;
//entry.IsUnicodeText = true;
if ((null != _unzipCallback) && !_unzipCallback.OnPreUnzip(entry))
continue; // 过滤
string filePathName = Path.Combine(_outputPath, entry.Name);
// 创建文件目录
if (entry.IsDirectory)
{
Directory.CreateDirectory(filePathName);
continue;
}
// 写入文件
try
{
using (FileStream fileStream = File.Create(filePathName))
{
byte[] bytes = new byte[1024];
while (true)
{
int count = zipInputStream.Read(bytes, 0, bytes.Length);
if (count > 0)
fileStream.Write(bytes, 0, count);
else
{
if (null != _unzipCallback)
_unzipCallback.OnPostUnzip(entry);
break;
}
}
}
}
catch (System.Exception _e)
{
Debug.LogError("[ZipUtility.UnzipFile]: " + _e.ToString());
if (null != _unzipCallback)
_unzipCallback.OnFinished(false);
return false;
}
}
}
if (null != _unzipCallback)
_unzipCallback.OnFinished(true);
return true;
}
解压的代码也是取自于网友,只是在解压时设置了ZipConstants.DefaultCodePage属性:
Encoding gbk = Encoding.GetEncoding("gbk");
ICSharpCode.SharpZipLib.Zip.ZipConstants.DefaultCodePage = gbk.CodePage;
配套dll下载百度盘:链接:https://pan.baidu.com/s/1mKFeLbYLVf00oRuEu5V7TQ 密码:9dad