using System;
using System.IO;
using UnityEngine;
using System.Text;
using System.Collections;
using UnityEngine.Networking;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
namespace XRTool.Util
{
///
/// 文件工具类
/// 下载,写入文件,断点续传,边下边存
/// 遍历,拷贝文件
/// 获取文件的MD5等
///
public class DataFileUtil
{
///
/// 预估的写入文件的速度,与真实速度无关,仅仅是模拟评估,预计写入用时
///
public const float WriteSpeed = 1024 * 1024 * 150f;
/////
///// 写入缓存的大小,如果越小,可能会引起卡顿(频繁访问数据)
/////
//public const int CacheSave = 1024 * 1024 * 2;
///
/// 图片格式
///
public static string[] TexturesType = new string[] { "BMP", "EXR", "GIF", "HDR", "IFF", "JPG", "PICT", "PNG", "PSD", "TGA", "TIFF" };
///
/// 视频格式
///
public static string[] MoviesType = new string[] { "MOV", "MPG", "MP4", "AVI", "ASF" };
///
/// 音频格式
///
public static string[] AudiosType = new string[] { "ACC", "AIFF", "IT", "MOD", "MPEG", "OGGVORBIS", "S3M",
"AIF", "WAV", "MP3", "OGG","XM","XMA","VAG","AUDIOQUEUE" };
public static int maxTryCount = 5;
///
/// 下载数据到本地,并将下载的数据返回给到上层应用
/// 此下载仅应用于可缓存的资源,图片文本等下载,大文件的下载请使用断点下载
///
///
///
///
///
///
///
public static IEnumerator DownLoadData(string url, string path,
Action completeData, DownloadHandler hander = null, Action downLoadProcess=null, bool isAsync = false)
{
bool isDowning = true;
UnityWebRequest web = null;
//DownloadHandlerTexture
yield return RequestDownData(url, (string error, UnityWebRequest req) =>
{
///下载成功后开始拷贝数据到本地
if (string.IsNullOrEmpty(error))
{
///同步存储方法
if (!isAsync)
{
SaveDataToFile(path, req.downloadHandler.data);
downLoadProcess?.Invoke(req.downloadHandler.data.Length, 1);
completeData?.Invoke(path, req);
return;
}
else
{
web = req;
///此时,已下载到内存中,但是仍未缓存至内存中,内存数据可用
completeData?.Invoke(null, req);
}
}
else
{
///下载出错
completeData?.Invoke(null, null);
//UnityLog.Instance.LogError(error);
}
isDowning = false;
}, hander, (float allLeng, float process) =>
{
///下载的进度,1/1.2,给存储留进度条显示,约等于0.89
downLoadProcess?.Invoke(allLeng, process / 1.12f);
});
///等待下载完成,此下载是下载到内存中
while (isDowning)
{
yield return 0;
}
if (isAsync && web != null)
{
//completeData?.Invoke(true, data);
yield return SaveDataToFile(path, web.downloadHandler.data, (float saveProcess) =>
{
///更新存储文件的进度
downLoadProcess?.Invoke(web.downloadHandler.data.Length, saveProcess * 0.1f + 0.9f);
}, (bool isSuccess, string filePath) =>
{
completeData?.Invoke(filePath, web);
});
}
web.Dispose();
}
//public static IEnumerator DownLoadData(string url, string path, Action completeData,
// DownloadHandler hander = null, Action downLoadProcess = null, bool isAsync = false)
//{
// bool isDowning = true;
// UnityWebRequest web = null;
// //DownloadHandlerTexture
// yield return RequestDownData(url, (string error, UnityWebRequest req) =>
// {
// ///下载成功后开始拷贝数据到本地
// if (string.IsNullOrEmpty(error))
// {
// ///同步存储方法
// if (!isAsync)
// {
// SaveDataToFile(path, req.downloadHandler.data);
// downLoadProcess?.Invoke(req.downloadHandler.data.Length, 1);
// completeData?.Invoke(path, req);
// return;
// }
// else
// {
// web = req;
// ///此时,已下载到内存中,但是仍未缓存至内存中,内存数据可用
// completeData?.Invoke(null, req);
// }
// }
// else
// {
// ///下载出错
// completeData?.Invoke(null, null);
// //UnityLog.Instance.LogError(error);
// }
// isDowning = false;
// }, hander, (float allLeng, float process) =>
// {
// ///下载的进度,1/1.2,给存储留进度条显示,约等于0.89
// downLoadProcess?.Invoke(allLeng, process / 1.12f);
// });
// ///等待下载完成,此下载是下载到内存中
// while (isDowning)
// {
// yield return 0;
// }
// if (isAsync && web != null)
// {
// //completeData?.Invoke(true, data);
// yield return SaveDataToFile(path, web.downloadHandler.data, (float saveProcess) =>
// {
// ///更新存储文件的进度
// downLoadProcess?.Invoke(web.downloadHandler.data.Length, saveProcess * 0.1f + 0.9f);
// }, (bool isSuccess, string filePath) =>
// {
// completeData?.Invoke(filePath, web);
// });
// }
//}
///
/// 请求后台数据接口
///
///
public static IEnumerator RequestData(string url, Action reqComplete, bool isPost = true,
Dictionary header = null, Dictionary form = null, Action complete = null)
{
///表单
using (UnityWebRequest web = isPost ? UnityWebRequest.Post(url, form) : UnityWebRequest.Get(url))
{
if (header != null)
{
foreach (var item in header)
{
web.SetRequestHeader(item.Key, item.Value);
}
}
yield return web.SendWebRequest();
if (web.isNetworkError || web.isHttpError)
{
UnityLog.Instance.LogError(web.error);
reqComplete?.Invoke(null);
complete?.Invoke();
yield break;
}
else
{
reqComplete?.Invoke(web.downloadHandler.text);
complete?.Invoke();
}
}
}
///
/// 获取资源的大小
///
///
///
///
public static IEnumerator GetDataSize(string url, Action getLen)
{
var headRequest = UnityWebRequest.Head(url);
yield return headRequest.SendWebRequest();
getLen?.Invoke(long.Parse(headRequest.GetResponseHeader("Content-Length")));
headRequest.Dispose();
}
///
/// 异步下载,此下载不再判断文件是否存在,直接走下载方法
/// 请在传值时先对DownInfo进行初始化判断
///
///
//public static IEnumerator DownLoadDataAsync(DownInfo info, int count = 0)
//{
// float watieTime = 0;
// while (Application.internetReachability == NetworkReachability.NotReachable)
// {
// UnityLog.Instance.LogError("No Internet Connect");
// yield return new WaitForSeconds(watieTime);
// watieTime += 0.1f;
// if (watieTime > 1)
// {
// watieTime = 1;
// }
// }
// DownInfoHandler handler = new DownInfoHandler(info);
// Dictionary form = new Dictionary();
// form.Add("appId", info.id.ToString());
// form.Add("searchId", info.searchId.ToString());
// form.Add("recommendId", info.recommendId.ToString());
// form.Add("word", info.word == null ? "" : info.word);
// using (UnityWebRequest web = UnityWebRequest.Post(info.server, form))
// {
// handler.SetWebRequest(web, info.lastVersionSize);
// web.disposeDownloadHandlerOnDispose = true;
// web.downloadHandler = handler;
// foreach (var item in UrlMgr.Instance.Header)
// {
// web.SetRequestHeader(item.Key, item.Value);
// }
// ///请求指定的长度
// web.SetRequestHeader("Range", info.downloadedFileLen.ToString());
// UnityLog.Instance.Log("bytes=" + info.downloadedFileLen + "-" + info.totalSize, 3);
// yield return web.SendWebRequest();
// if (web.isNetworkError || web.isHttpError)
// {
// if (count < maxTryCount)
// {
// UnityLog.Instance.LogError(info.fileName + "down error ,try again: " + count + web.error + "bytes=" + info.downloadedFileLen + "-" + info.totalSize);
// count++;
// web.Dispose();
// handler.ErrorDispose(false);
// yield return new WaitForSeconds(0.1f);
// yield return DownLoadDataAsync(info, count);
// yield break;
// }
// UnityLog.Instance.LogError(web.error + "bytes=" + info.downloadedFileLen + "-" + info.totalSize);
// handler.ErrorDispose();
// }
// else
// {
// }
// web.Dispose();
// }
//}
///
/// 断点续传/下载,边下边存
/// 适用于大文件下载。如果是简单的文本或者图片,尽量不要使用此接口
///
/// 目标地址
/// 本地文件路径
/// 下载进度
/// 返回下载的状态,成功或失败,成功后返回改文件的路径
///
//public static IEnumerator DownLoadDataAsync(string url, string path, Action downLoadProcess, Action complete)
//{
// ///获取文件的大小
// FileStream fs = null;
// long curLen = 0;
// ///文件读写异常,返回错误
// try
// {
// string dir = Path.GetDirectoryName(path);
// if (!Directory.Exists(dir))
// {
// Directory.CreateDirectory(dir);
// }
// fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
// curLen = fs.Length;
// UnityLog.Instance.Log("当前文件大小" + curLen, 2);
// }
// catch (Exception ex)
// {
// if (fs != null)
// {
// fs.Close();
// }
// UnityLog.Instance.LogError(path + ex.ToString());
// downLoadProcess.Invoke(curLen, 0);
// complete?.Invoke(false, ex.ToString());
// yield break;
// }
// ///请求获取文件的大小
// ///已下载完成,无需再次下载
// long totalLength = 0;
// yield return GetDataSize(url, (size) =>
// {
// totalLength = size;
// });
// ///当前文件的大小和云端文件大小一致
// ///理论上不会出现这个问题
// if (curLen == totalLength)
// {
// fs.Close();
// downLoadProcess.Invoke(totalLength, 1);
// complete?.Invoke(true, path);
// yield break;
// }
// ///文件异常,删除文件,重新下载
// ///理论上不会出现这个问题
// else if (curLen > totalLength)
// {
// UnityLog.Instance.LogError("文件大小异常" + curLen + "__" + totalLength);
// fs.Close();
// File.Delete(path);
// fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
// curLen = fs.Length;
// }
// fs.Seek(curLen, SeekOrigin.Begin);
// bool isSuccess = true;
// yield return RequestDownData(url, (byte[] data, int len) =>
// {
// if (isSuccess && data.Length > 0)
// {
// try
// {
// fs.Write(data, 0, len);
// fs.Flush();
// curLen += len;
// downLoadProcess?.Invoke(curLen, curLen * 1f / totalLength);
// }
// catch (Exception ex)
// {
// UnityLog.Instance.LogError(ex.ToString());
// isSuccess = false;
// return;
// }
// }
// else
// {
// ///理论上不会出现这个问题,除非出现异常情况如内存不足等
// //complete?.Invoke(isSuccess, path);
// UnityLog.Instance.LogError("Down Error:" + url);
// }
// }, totalLength, curLen);
// fs.Close();
// downLoadProcess.Invoke(totalLength, 1);
// complete?.Invoke(isSuccess, path);
//}
///
/// Get请求下载数据,断点下载,边下载边返回数据进行存储
///
/// url
/// 返回获取的数据
/// 文件的总大小
/// 已下载的数据
///
//public static IEnumerator RequestDownData(string url, Action downData, long allLen, long downedLength = 0)
//{
// //float downTime = Time.time;
// UnityWebRequest web = UnityWebRequest.Get(url);
// web.disposeDownloadHandlerOnDispose = true;
// DataDownLoadHandler ddh = new DataDownLoadHandler();
// web.downloadHandler = ddh;
// ddh.OnReceiveData += downData;
// ///请求指定的长度
// web.SetRequestHeader("Range", "bytes=" + downedLength + "-" + allLen);
// yield return web.SendWebRequest();
// web.Dispose();
//}
///
/// 从URl下载指定的资源
///
/// 资源的地址,可以是网络路径,也可以是本地文件路径
/// 下载的进度,当前已下载文件大小,以及进度
///
/// 请求的参数,如果为空代表Get请求,不为空代表Post请求
///
public static IEnumerator RequestDownData(string url, Action complete, DownloadHandler hander = null, Action updateProcess = null, WWWForm form = null)
{
UnityWebRequest web;
Debug.Log("RequestDownData" + url);
if (form == null)
{
web = UnityWebRequest.Get(url);
}
else
{
web = UnityWebRequest.Post(url, form);
}
if (hander != null)
{
web.downloadHandler = hander;
}
web.SendWebRequest();
while (!web.isDone)
{
updateProcess?.Invoke(web.downloadedBytes, web.downloadProgress);
yield return 0;
}
if (web.isDone)
{
updateProcess?.Invoke(web.downloadedBytes, 1);
}
if (web.isNetworkError || web.isHttpError)
{
complete?.Invoke(web.error, web);
Debug.LogError(web.error+url);
}
else
{
complete?.Invoke(null, web);
}
web.Dispose();
}
///
/// 上传数据到服务端,并得到服务器返回的结果
/// 与下面的RequestDownData类似,但是更新上传进度,适用于文件上传
///
///
///
///
///
///
public static IEnumerator RequestUpLoadData(string url, WWWForm form, Action updateProcess, Action complete)
{
UnityWebRequest web = UnityWebRequest.Post(url, form);
web.SendWebRequest();
while (!web.isDone)
{
updateProcess?.Invoke(web.uploadedBytes, web.uploadProgress);
yield return 0;
}
if (web.isDone)
{
updateProcess?.Invoke(web.uploadedBytes, 1);
}
if (web.isNetworkError || web.isHttpError)
{
complete?.Invoke(web.error, web);
}
else
{
complete?.Invoke(null, web);
}
web.Dispose();
}
///
/// 是否是忽略的文件类型
///
///
///
public static bool isIgnoreExtension(string ignoreExtension, string suffix)
{
string[] igs = ignoreExtension.Split('|', ' ', ',');
for (int i = 0; i < igs.Length; i++)
{
if (igs[i] == suffix)
{
return true;
}
}
return false;
}
///
/// 保存文本文件到本地
/// 同步方法
///
public static bool SaveDataToFile(string path, string txt)
{
try
{
if (!string.IsNullOrEmpty(txt))
{
File.WriteAllText(path, txt);
return true;
}
}
catch (Exception ex)
{
UnityLog.Instance.LogError(path + ex.ToString());
}
return false;
}
///
/// 保存二进制字节文件到本地,同步方法
///
///
///
public static bool SaveDataToFile(string path, byte[] data)
{
try
{
string dir = Path.GetDirectoryName(path);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
FileStream fs = new FileStream(path, FileMode.Create);
fs.Write(data, 0, data.Length);
fs.Dispose();
fs.Close();
return true;
}
catch (Exception ex)
{
UnityLog.Instance.LogError(path + ex.ToString());
}
return false;
}
///
/// 异步保存文本文件
///
///
///
///
///
public static IEnumerator SaveDataToFile(string path, string txt, Action saveProcess, Action onComplete)
{
yield return SaveDataToFile(path, Encoding.Default.GetBytes(txt), saveProcess, onComplete);
}
///
/// 保存二进制字节文件到本地,异步方法
///
///
///
private static IEnumerator SaveDataToFile(string path, byte[] data, Action saveProcess, Action onComplete)
{
bool isSuccess = false;
if (data != null && data.Length > 0)
{
Task task = null;
FileStream fs = null;
float allData = data.Length;
try
{
fs = new FileStream(path, FileMode.Create);
task = fs.WriteAsync(data, 0, data.Length);
isSuccess = true;
}
catch (Exception ex)
{
UnityLog.Instance.LogError(path + ex.ToString());
path = ex.ToString();
isSuccess = false;
}
float tmp = 0;
float allTime = data.Length / WriteSpeed;
///预计存储完成的时间
while (task != null && !task.IsCompleted)
{
if (tmp < allTime)
{
tmp += Time.deltaTime;
}
saveProcess?.Invoke(tmp / allTime);
yield return 0;
}
saveProcess(1);
fs.Dispose();
fs.Close();
}
onComplete?.Invoke(isSuccess, path);
}
///
/// 广度优先,遍历文件
///
///
///
public static void FindFileBreadth(string path, Action callBack)
{
try
{
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] fis = di.GetFiles();
for (int i = 0; i < fis.Length; i++)
{
callBack?.Invoke(fis[i].FullName);
}
DirectoryInfo[] dis = di.GetDirectories();
for (int j = 0; j < dis.Length; j++)
{
FindFileBreadth(dis[j].FullName, callBack);
}
}
catch (Exception ex)
{
UnityLog.Instance.LogError(ex.ToString());
}
}
///
/// 深度优先,遍历文件
///
///
public static void FindFileByDepth(string dir, Action callBack)
{
try
{
DirectoryInfo d = new DirectoryInfo(dir);
FileSystemInfo[] fsinfos = d.GetFileSystemInfos();
foreach (FileSystemInfo fsinfo in fsinfos)
{
if (fsinfo is DirectoryInfo)
{
FindFileByDepth(fsinfo.FullName, callBack);
}
else
{
callBack?.Invoke(fsinfo.FullName);
}
}
}
catch (Exception ex)
{
UnityLog.Instance.LogError(ex.ToString());
}
}
///
/// 获取文件MD5值
///
/// 文件绝对路径
/// MD5值
public static string GetMD5HashFromFile(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (Exception ex)
{
throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
}
}
///
/// 重命名文件
///
///
///
public static void ReNameFile(string file, string newFile)
{
if (File.Exists(file))
{
try
{
string dir = Path.GetDirectoryName(newFile);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
if (File.Exists(newFile))
{
File.Delete(newFile);
}
FileInfo info = new FileInfo(file);
info.MoveTo(newFile);
}
catch (Exception ex)
{
UnityLog.Instance.LogError(file + " is error" + ex.ToString());
}
}
}
///
/// 删除文件
///
///
///
public static void DelFile(string file)
{
UnityLog.Instance.Log(file + " is Del", 3);
if (File.Exists(file))
{
try
{
File.Delete(file);
}
catch (Exception ex)
{
UnityLog.Instance.LogError(file + " is error" + ex.ToString());
}
}
}
///
/// 拷贝文件
///
///
///
/// 是否覆盖
///
public static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)
{
bool ret = false;
try
{
SourcePath = SourcePath.EndsWith(@"\") ? SourcePath : SourcePath + @"\";
DestinationPath = DestinationPath.EndsWith(@"\") ? DestinationPath : DestinationPath + @"\";
if (Directory.Exists(SourcePath))
{
if (Directory.Exists(DestinationPath) == false)
Directory.CreateDirectory(DestinationPath);
foreach (string fls in Directory.GetFiles(SourcePath))
{
FileInfo flinfo = new FileInfo(fls);
flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting);
}
foreach (string drs in Directory.GetDirectories(SourcePath))
{
DirectoryInfo drinfo = new DirectoryInfo(drs);
if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false)
ret = false;
}
}
ret = true;
}
catch (Exception ex)
{
ret = false;
UnityLog.Instance.LogError(ex.ToString());
}
return ret;
}
///
/// 文件是否是图片
///
///
///
public static bool IsMoviesFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
string exten = Path.GetExtension(fileName);
return IsMediaType(exten.ToUpper(), MoviesType);
}
return false;
}
public static bool IsTextureFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
string exten = Path.GetExtension(fileName);
return IsMediaType(exten.ToUpper(), TexturesType);
}
return false;
}
///
/// 判断是否是音频文件
/// MP3,WAV等
///
///
///
public static bool IsAudioFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
string exten = Path.GetExtension(fileName);
return IsMediaType(exten.ToUpper(), AudiosType);
}
return false;
}
///
/// 是否是多媒体文件:图片,视频,音频
///
///
///
///
public static bool IsMediaType(string fileName, string[] types)
{
if (!string.IsNullOrEmpty(fileName) && types != null)
{
for (int i = 0; i < types.Length; i++)
{
if (TexturesType[i] == fileName)
{
return true;
}
}
}
return false;
}
///
/// 是否多媒体文件
/// 音频,视频,图片
///
///
///
public static bool IsMediaType(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
string exten = Path.GetExtension(fileName);
exten = exten.ToUpper();
return IsMediaType(exten, TexturesType) || IsMediaType(exten, MoviesType) || IsMediaType(exten, AudiosType);
}
return false;
}
///
/// 是否存在某文件
///
///
///
public static bool Exists(string file)
{
return File.Exists(file);
}
}
}