2024-12-14 18:27:59 +08:00

344 lines
10 KiB
C#

/****************************************************************************
* Copyright (c) 2017 snowcold
* Copyright (c) 2017 ~ 2020.10 liangxie
*
* https://qframework.cn
* https://github.com/liangxiegame/QFramework
* https://gitee.com/liangxiegame/QFramework
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
****************************************************************************/
using System.Collections.Generic;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using UnityEngine;
namespace QFramework
{
public class ZipFileHelper : IZipFileHelper
{
private List<string> mSearchDirList = new List<string>();
private string mStreamingAssetsPath;
private ZipFile mZipFile = null;
public ZipFile GetZipFile()
{
return mZipFile;
}
public ZipFileHelper()
{
mSearchDirList.Add(AssetBundlePathHelper.PersistentDataPath4Res);
mStreamingAssetsPath = AssetBundlePathHelper.StreamingAssetsPath;
#if (UNITY_ANDROID) && !UNITY_EDITOR
if (mZipFile == null)
{
mZipFile = new ZipFile(File.Open(UnityEngine.Application.dataPath, FileMode.Open, FileAccess.Read));
}
#endif
}
~ZipFileHelper()
{
#if UNITY_ANDROID && !UNITY_EDITOR
if (mZipFile != null)
{
mZipFile.Close();
mZipFile = null;
}
#endif
}
public void InitStreamingAssetPath()
{
mStreamingAssetsPath = AssetBundlePathHelper.StreamingAssetsPath;
}
//在包内查找是否有改资源
private bool FindResInAppInternal(string fileRelativePath)
{
#if UNITY_IPHONE && !UNITY_EDITOR
string absoluteFilePath = FindFilePathInternal(fileRelativePath);
return !string.IsNullOrEmpty(absoluteFilePath);
#elif UNITY_ANDROID && !UNITY_EDITOR
int entryIndex = mZipFile.FindEntry(string.Format("assets/{0}", fileRelativePath), false);
return entryIndex != -1;
#else
string absoluteFilePath = string.Format("{0}{1}", mStreamingAssetsPath, fileRelativePath);
return File.Exists(absoluteFilePath);
#endif
}
private void AddSearchPath(string dir)
{
mSearchDirList.Add(dir);
}
public bool FileExists(string fileRelativePath)
{
#if UNITY_IPHONE && !UNITY_EDITOR
string absoluteFilePath = FindFilePath(fileRelativePath);
return (!string.IsNullOrEmpty(absoluteFilePath) && File.Exists(absoluteFilePath));
#elif UNITY_ANDROID && !UNITY_EDITOR
string absoluteFilePath = FindFilePathInExteral(fileRelativePath);
//先到外存去找
if (!string.IsNullOrEmpty(absoluteFilePath))
{
return File.Exists(absoluteFilePath);
}
else
{
if (mZipFile == null)
{
return false;
}
return mZipFile.FindEntry(string.Format("assets/{0}", fileRelativePath), true) >= 0;
}
#else
string filePathStandalone = string.Format("{0}{1}", mStreamingAssetsPath, fileRelativePath);
return (!string.IsNullOrEmpty(filePathStandalone) && File.Exists(filePathStandalone));
#endif
}
public Stream OpenReadStream(string absFilePath)
{
if (string.IsNullOrEmpty(absFilePath))
{
return null;
}
#if UNITY_ANDROID && !UNITY_EDITOR
//Android 包内
if (absFilePath.Contains(".apk/"))
{
return OpenStreamInZip(absFilePath);
}
#endif
FileInfo fileInfo = new FileInfo(absFilePath);
if (!fileInfo.Exists)
{
return null;
}
return fileInfo.OpenRead();
}
public void GetFileInInner(string fileName, List<string> outResult)
{
#if UNITY_ANDROID && !UNITY_EDITOR
//Android 包内
GetFileInZip(mZipFile, fileName, outResult);
return;
#endif
AssetBundlePathHelper.GetFileInFolder(AssetBundlePathHelper.StreamingAssetsPath, fileName, outResult);
}
public byte[] ReadSync(string fileRelativePath)
{
string absoluteFilePath = FindFilePathInExteral(fileRelativePath);
if (!string.IsNullOrEmpty(absoluteFilePath))
{
return ReadSyncExtenal(fileRelativePath);
}
return ReadSyncInternal(fileRelativePath);
}
public byte[] ReadSyncByAbsoluteFilePath(string absoluteFilePath)
{
if (File.Exists(absoluteFilePath))
{
FileInfo fileInfo = new FileInfo(absoluteFilePath);
return ReadFile(fileInfo);
}
else
{
return null;
}
}
private byte[] ReadSyncExtenal(string fileRelativePath)
{
string absoluteFilePath = FindFilePathInExteral(fileRelativePath);
if (!string.IsNullOrEmpty(absoluteFilePath))
{
FileInfo fileInfo = new FileInfo(absoluteFilePath);
return ReadFile(fileInfo);
}
return null;
}
private byte[] ReadSyncInternal(string fileRelativePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
return ReadDataInAndriodApk(fileRelativePath);
#else
string absoluteFilePath = FindFilePathInternal(fileRelativePath);
if (!string.IsNullOrEmpty(absoluteFilePath))
{
FileInfo fileInfo = new FileInfo(absoluteFilePath);
return ReadFile(fileInfo);
}
#endif
return null;
}
private byte[] ReadFile(FileInfo fileInfo)
{
using (FileStream fileStream = fileInfo.OpenRead())
{
byte[] byteData = new byte[fileStream.Length];
fileStream.Read(byteData, 0, byteData.Length);
return byteData;
}
}
private string FindFilePathInExteral(string file)
{
string filePath;
for (int i = 0; i < mSearchDirList.Count; ++i)
{
filePath = string.Format("{0}/{1}", mSearchDirList[i], file);
if (File.Exists(filePath))
{
return filePath;
}
}
return string.Empty;
}
private string FindFilePath(string file)
{
// 先到搜索列表里找
string filePath = FindFilePathInExteral(file);
if (!string.IsNullOrEmpty(filePath))
{
return filePath;
}
// 在包内找
filePath = FindFilePathInternal(file);
if (!string.IsNullOrEmpty(filePath))
{
return filePath;
}
return null;
}
private string FindFilePathInternal(string file)
{
string filePath = string.Format("{0}{1}", mStreamingAssetsPath, file);
if (File.Exists(filePath))
{
return filePath;
}
return null;
}
private Stream OpenStreamInZip(string absPath)
{
string tag = "!/assets/";
string androidFolder = absPath.Substring(0, absPath.IndexOf(tag));
int startIndex = androidFolder.Length + tag.Length;
string relativePath = absPath.Substring(startIndex, absPath.Length - startIndex);
ZipEntry zipEntry = mZipFile.GetEntry(string.Format("assets/{0}", relativePath));
if (zipEntry != null)
{
return mZipFile.GetInputStream(zipEntry);
}
else
{
Debug.LogError($"Can't Find File {absPath}");
}
return null;
}
public void GetFileInZip(ZipFile zipFile, string fileName, List<string> outResult)
{
int totalCount = 0;
foreach (var entry in zipFile)
{
++totalCount;
ICSharpCode.SharpZipLib.Zip.ZipEntry e = entry as ICSharpCode.SharpZipLib.Zip.ZipEntry;
if (e != null)
{
if (e.IsFile)
{
if (e.Name.EndsWith(fileName))
{
outResult.Add(zipFile.Name + "/!/" + e.Name);
}
}
}
}
}
private byte[] ReadDataInAndriodApk(string fileRelativePath)
{
byte[] byteData = null;
//Log.I("Read From In App...");
if (mZipFile == null)
{
Debug.LogError("can't open apk");
return null;
}
//Log.I("Begin Open Zip...");
ZipEntry zipEntry = mZipFile.GetEntry(string.Format("assets/{0}", fileRelativePath));
//Log.I("End Open Zip...");
if (zipEntry != null)
{
//Log.I("Begin Read Zip...");
var stream = mZipFile.GetInputStream(zipEntry);
byteData = new byte[zipEntry.Size];
//Log.I("Read Zip Length:" + byteData.Length);
stream.Read(byteData, 0, byteData.Length);
stream.Close();
}
else
{
Debug.LogError(string.Format("Can't Find File {0}", fileRelativePath));
}
return byteData;
}
}
}