public static Dictionary <string, FileDetailInfo> StringToFileList(string content, out FileListParseError error) { error = FileListParseError.Null; Dictionary <string, FileDetailInfo> retList = new Dictionary <string, FileDetailInfo> (); string[] detailInfos = content.Split(DetailSeparator); //因为在序列化时,每一条信息后边都追加了一个DetailSeparator,所以detailInfos数组最后一条回事null for (int i = 0; i < detailInfos.Length - 1; ++i) { if (string.IsNullOrEmpty(detailInfos [i])) { error = FileListParseError.DetailInfoIsNull; return(null); } FileDetailInfo info = StringToFileDetailInfo(detailInfos [i], out error); if (null == info) { return(null); } if (retList.ContainsKey(info.fileName)) { error = FileListParseError.FileRepeat; return(null); } retList.Add(info.fileName, info); } return(retList); }
private static void AppendDetailInfo(StringBuilder sb, FileDetailInfo info) { sb.Append(info.fileName + VariableSeparator); sb.Append(info.filePath + VariableSeparator); sb.Append(info.fileMd5 + VariableSeparator); sb.Append(info.fileLength); }
public static string DetailInfoToString(FileDetailInfo detailInfo) { StringBuilder sb = new StringBuilder(); AppendDetailInfo(sb, detailInfo); sb.Append(DetailSeparator); return(sb.ToString()); }
private static void SeachDirectoryFIles(Dictionary <string, NewFileSystem.FileDetailInfo> fileListDic, DirectoryInfo directoryInfo, string relativePath, string targetPath, bool isServerBuild) { FileInfo[] fileInfos = directoryInfo.GetFiles(); if (isServerBuild && !Directory.Exists(targetPath)) { Directory.CreateDirectory(targetPath); } for (int i = 0; i < fileInfos.Length; ++i) { NewFileSystem.FileDetailInfo detailInfo = new NewFileSystem.FileDetailInfo(); FileInfo fileInfo = fileInfos [i]; if (fileInfo.Name == ".DS_Store") { continue; } if (fileInfo.Extension == ".meta") { continue; } if (fileInfo.Length == 0) { Debug.LogError("Find file size is zero " + fileInfo.FullName); continue; } byte[] fileContent = File.ReadAllBytes(fileInfo.FullName); detailInfo.fileMd5 = Utils.MD5(fileContent); detailInfo.fileName = fileInfo.Name; detailInfo.fileLength = fileInfo.Length; detailInfo.filePath = relativePath; if (fileListDic.ContainsKey(detailInfo.fileName)) { Debug.LogError("Has same name file " + fileInfo.FullName); } else { fileListDic.Add(detailInfo.fileName, detailInfo); } if (isServerBuild) { string targetFilePath = Path.Combine(targetPath, detailInfo.fileMd5); if (File.Exists(targetFilePath)) { File.Delete(targetFilePath); } File.Copy(fileInfo.FullName, targetFilePath); } } DirectoryInfo[] directoryInfos = directoryInfo.GetDirectories(); for (int i = 0; i < directoryInfos.Length; ++i) { SeachDirectoryFIles(fileListDic, directoryInfos [i] , Path.Combine(relativePath, directoryInfos [i].Name) , Path.Combine(targetPath, directoryInfos [i].Name) , isServerBuild); } }
public static string FileListToString(Dictionary <string, FileDetailInfo> fileListDic) { StringBuilder sb = new StringBuilder(); var enumerator = fileListDic.GetEnumerator(); while (enumerator.MoveNext()) { FileDetailInfo detailInfo = enumerator.Current.Value; AppendDetailInfo(sb, detailInfo); sb.Append(DetailSeparator); } return(sb.ToString()); }
private void GetUpdatedFile() { mSynchronizeData.needDownloadSet = new List <FileDetailInfo> (); var enumerator = mSynchronizeData.serverFileListDic.GetEnumerator(); while (enumerator.MoveNext()) { FileDetailInfo serverDetailInfo = enumerator.Current.Value; FileDetailInfo localDetailInfo = null; if (!mSynchronizeData.persistentFileListDic.TryGetValue(serverDetailInfo.fileName, out localDetailInfo)) { FileDetailInfo streamingDetailInfo; if (null != mSynchronizeData.streamingFileListDic && mSynchronizeData.streamingFileListDic.TryGetValue(serverDetailInfo.fileName, out streamingDetailInfo)) { if (streamingDetailInfo.fileMd5 != serverDetailInfo.fileMd5 || streamingDetailInfo.filePath != serverDetailInfo.filePath) { mSynchronizeData.needDownloadSet.Add(serverDetailInfo); } else { //在StreamingAssets目录下存在相同的文件,不需要下载 } } else { mSynchronizeData.needDownloadSet.Add(serverDetailInfo); } continue; } if (localDetailInfo.fileMd5 != serverDetailInfo.fileMd5) { mSynchronizeData.needDownloadSet.Add(serverDetailInfo); string localFilePath = FileSystemUtils.GetFileRelativePath(localDetailInfo.fileName, localDetailInfo.filePath, true); GameMain.Instance.FileOperateMgr.DeleteIfExist(localFilePath); mSynchronizeData.persistentFileListDic.Remove(localDetailInfo.fileName); mLocalFileListHasChange = true; continue; } if (localDetailInfo.filePath != serverDetailInfo.filePath) { string fromLocalFilePath = FileSystemUtils.GetFileRelativePath(localDetailInfo.fileName, localDetailInfo.filePath, true); string toLocalFilePath = FileSystemUtils.GetFileRelativePath(serverDetailInfo.fileName, serverDetailInfo.filePath, true); GameMain.Instance.FileOperateMgr.MoveFile(fromLocalFilePath, toLocalFilePath); localDetailInfo.filePath = serverDetailInfo.filePath; mLocalFileListHasChange = true; } } }
private void CheckDiskFile(DirectoryInfo directoryInfo, string relativePath) { FileInfo[] fileInfos = directoryInfo.GetFiles(); for (int i = 0; i < fileInfos.Length; ++i) { FileInfo fileInfo = fileInfos [i]; string fileName = fileInfo.Name; bool needRemove = false; FileDetailInfo info = null; if (mSynchronizeData.persistentFileListDic.TryGetValue(fileName, out info)) { //文件列表中存在,需要判断路径是否一致 if (relativePath != info.filePath) { //路径不一致,需要删除文件 needRemove = true; } else { //路径一致时,在文件列表到硬盘的检查中已经覆盖,不需要处理 } } else { //文件列表中不存在 needRemove = true; } if (needRemove) { string fileRelativePath = FileSystemUtils.GetFileRelativePath(fileName, relativePath, true); GameMain.Instance.FileOperateMgr.DeleteIfExist(fileRelativePath); mSynchronizeData.persistentFileListDic.Remove(fileName); mSynchronizeData.localVersionInfo.Clear(); } } DirectoryInfo[] childDirectories = directoryInfo.GetDirectories(); for (int i = 0; i < childDirectories.Length; ++i) { DirectoryInfo childDirectory = childDirectories [i]; CheckDiskFile(childDirectory, Path.Combine(relativePath, childDirectory.Name)); } if (directoryInfo.GetFiles().Length == 0 && directoryInfo.GetDirectories().Length == 0) { directoryInfo.Delete(); } }
private void GenerateCopyList() { bool hasPersistentListChanged = false; Dictionary <string, FileDetailInfo> .Enumerator enumerateo = mStreamingFileListDic.GetEnumerator(); while (enumerateo.MoveNext()) { string fileName = enumerateo.Current.Key; FileDetailInfo streamDetailInfo = enumerateo.Current.Value; FileDetailInfo persistentDetailInfo = null; if (null == mPersistentFileListDic || !mPersistentFileListDic.TryGetValue(fileName, out persistentDetailInfo)) { mCopyList.Add(fileName); } else { if (persistentDetailInfo.fileMd5 != streamDetailInfo.fileMd5 || persistentDetailInfo.filePath != streamDetailInfo.filePath) { string relativePath = FileSystemUtils.GetFileRelativePath(fileName, persistentDetailInfo.filePath, true); GameMain.Instance.FileOperateMgr.DeleteIfExist(relativePath); mCopyList.Add(fileName); hasPersistentListChanged = true; mPersistentFileListDic.Remove(fileName); } } } if (hasPersistentListChanged) { //使Persistent目录下的文件列表和实际文件一致,避免下一阶段拷贝中断造成文件列表和实际文件不一致 string errorStr; FileErrorCode errorCode = FileListUtils.WriteFileList(mPersistentFileListDic, out errorStr); if (FileErrorCode.Null != errorCode) { OnError("GenerateCopyList write persistent fileList " + errorCode.ToString() + " " + errorStr); return; } } mCopyFileMaxCount = mCopyList.Count; CopyFiles(); }
private void CopyFiles() { Lancher.Instance.SetTips("请稍等,正在解压资源......(" + (mCopyFileMaxCount - mCopyList.Count).ToString() + "/" + mCopyFileMaxCount + ")"); if (mCopyList.Count == 0) { mHdlOnFinish.Invoke(); return; } string fileName = mCopyList[mCopyList.Count - 1]; mCopyList.RemoveAt(mCopyList.Count - 1); FileDetailInfo fileInfo = mStreamingFileListDic [fileName]; string relativePath = FileSystemUtils.GetFileRelativePath(fileName, fileInfo.filePath, true); this.StartCoroutine(LoadFile(relativePath, delegate(byte[] fileBytes) { GameMain.Instance.FileOperateMgr.CreateDirIfNotExist(Path.GetDirectoryName(relativePath)); string fileOpeErrorStr; FileErrorCode errorCode = FileOperateUtils.TryFileWrite(delegate(){ Logger.LogInfo("AndroidStreamingCopy copy file " + relativePath); GameMain.Instance.FileOperateMgr.WriteBinaryFile(relativePath, fileBytes); }, out fileOpeErrorStr); if (FileErrorCode.Null != errorCode) { OnError("AndroidStreamingCopy Write " + relativePath + " " + errorCode.ToString() + " " + fileOpeErrorStr); return; } errorCode = FileOperateUtils.TryFileWrite(delegate(){ string detailStr = FileListUtils.DetailInfoToString(fileInfo); GameMain.Instance.FileOperateMgr.WriteTextFile(mPersistentFileListRelativePath, detailStr, true); }, out fileOpeErrorStr); if (FileErrorCode.Null != errorCode) { OnError("AndroidStreamingCopy write fileList " + errorCode.ToString() + " " + fileOpeErrorStr); return; } CopyFiles(); }, delegate() { OnError("Load streaming FileList"); })); }
private static FileDetailInfo StringToFileDetailInfo(string content, out FileListParseError errorType) { errorType = FileListParseError.Null; string[] detailInfos = content.Split(VariableSeparator); if (detailInfos.Length != 4) { errorType = FileListParseError.DetailInfoElementCountError; return(null); } FileDetailInfo info = new FileDetailInfo(); info.fileName = detailInfos[0]; info.filePath = detailInfos[1]; info.fileMd5 = detailInfos[2]; if (!long.TryParse(detailInfos [3], out info.fileLength)) { errorType = FileListParseError.DetailInfoLengthError; return(null); } return(info); }
/// <summary> /// 保证内存中的文件列表和硬盘中的所有的真实文件一致,但是可能会和硬盘中的文件列表不一致 /// </summary> private void InfoCheck() { List <string> removeList = new List <string> (); Dictionary <string, FileDetailInfo> .Enumerator enumerator = mSynchronizeData.persistentFileListDic.GetEnumerator(); while (enumerator.MoveNext()) { FileDetailInfo detailInfo = enumerator.Current.Value; string localFilePath = FileSystemUtils.GetFileRelativePath(detailInfo.fileName, detailInfo.filePath, true); if (!GameMain.Instance.FileOperateMgr.IsFileExist(localFilePath)) { //也有可能只是文件在其他目录,为了逻辑简单不做文件目录的恢复功能,如果文件目录不一致,就会直接删除掉,在后面的阶段重新下载 removeList.Add(detailInfo.fileName); continue; } long fileLength = GameMain.Instance.FileOperateMgr.GetFileLength(localFilePath); if (fileLength != detailInfo.fileLength) { removeList.Add(detailInfo.fileName); GameMain.Instance.FileOperateMgr.DeleteIfExist(localFilePath); continue; } } if (removeList.Count > 0) { for (int i = 0; i < removeList.Count; ++i) { mSynchronizeData.persistentFileListDic.Remove(removeList [i]); } mSynchronizeData.localVersionInfo.Clear(); } string relativePath = FileSystemUtils.GetFolderRelativePath(string.Empty); DirectoryInfo directoryInfo = GameMain.Instance.FileOperateMgr.GetDirectoryInfo(relativePath); CheckDiskFile(directoryInfo, string.Empty); }
private void RemoveUnusedFileList() { //找到本地存在,但是服务器中不存在的文件,在硬盘中删除 var enumerator = mSynchronizeData.persistentFileListDic.GetEnumerator(); List <FileDetailInfo> removeList = new List <FileDetailInfo> (); while (enumerator.MoveNext()) { FileDetailInfo fileInfo = enumerator.Current.Value; if (mSynchronizeData.serverFileListDic.ContainsKey(enumerator.Current.Key)) { continue; } removeList.Add(enumerator.Current.Value); } for (int i = 0; i < removeList.Count; ++i) { FileDetailInfo removeFileInfo = removeList [i]; string filePath = FileSystemUtils.GetFileRelativePath(removeFileInfo.fileName, removeFileInfo.filePath, true); GameMain.Instance.FileOperateMgr.DeleteIfExist(filePath); mSynchronizeData.persistentFileListDic.Remove(removeFileInfo.fileName); mLocalFileListHasChange = true; } }
/// <summary> /// 加载文件列表和Version信息,并做内容合法检查 /// </summary> private void LoadInfo() { string localVersionFilePath = FileSystemUtils.GetFileRelativePath(FileDownloadData.VersionFileName, string.Empty); if (GameMain.Instance.FileOperateMgr.IsFileExist(localVersionFilePath)) { string localVersionContent = GameMain.Instance.FileOperateMgr.ReadAsText(localVersionFilePath); mSynchronizeData.localVersionInfo = Newtonsoft.Json.JsonConvert.DeserializeObject <LocalVersionInfo> (localVersionContent); } if (null == mSynchronizeData.localVersionInfo) { mSynchronizeData.localVersionInfo = new LocalVersionInfo(); mSynchronizeData.localVersionInfo.Clear(); } string localFileListFilePath = FileSystemUtils.GetFileRelativePath(FileDownloadData.FileListFileName, string.Empty); Dictionary <string, FileDetailInfo> fileListDic = null; if (GameMain.Instance.FileOperateMgr.IsFileExist(localFileListFilePath)) { string fileListContent = GameMain.Instance.FileOperateMgr.ReadAsText(localFileListFilePath); FileListUtils.FileListParseError error = FileListUtils.FileListParseError.Null; fileListDic = FileListUtils.StringToFileList(fileListContent, out error); if (FileListUtils.FileListParseError.Null != error) { //文件列表已经被破坏,所以直接删除文件 GameMain.Instance.FileOperateMgr.DeleteIfExist(localVersionFilePath); GameMain.Instance.FileOperateMgr.DeleteIfExist(localFileListFilePath); } else { string localFileListMd5 = Utils.MD5(fileListContent); if (localFileListMd5 != mSynchronizeData.localVersionInfo.persistentMd5) { //文件列表被修改 mSynchronizeData.localVersionInfo.Clear(); } } } if (null == fileListDic) { //如果文件列表不存在,那么有可能是被其他系统删除,也有可能是文件解析失败,所以清空localVersionInfo,保证一定能够进入CompareFileListState状态 mSynchronizeData.localVersionInfo.Clear(); mSynchronizeData.persistentFileListDic = new Dictionary <string, FileDetailInfo> (); } else { List <string> removeList = new List <string> (); Dictionary <string, FileDetailInfo> .Enumerator enumerator = fileListDic.GetEnumerator(); while (enumerator.MoveNext()) { FileDetailInfo detailInfo = enumerator.Current.Value; if (detailInfo.IsInvalid()) { removeList.Add(enumerator.Current.Key); } } if (removeList.Count > 0) { //有部分信息是不合法的,那么一定需要进入CompareFileListState状态 mSynchronizeData.localVersionInfo.Clear(); for (int i = 0; i < removeList.Count; ++i) { fileListDic.Remove(removeList [i]); } } mSynchronizeData.persistentFileListDic = fileListDic; } }
private void DownLoadFile() { if (mSynchronizeData.needDownloadSet.Count == 0) { mNextHandler.Invoke(FileDownloadStateId.WritePersistentVersionFile); return; } ShowTipInfo(); FileDetailInfo downloadFileInfo = mSynchronizeData.needDownloadSet [mSynchronizeData.needDownloadSet.Count - 1]; mSynchronizeData.needDownloadSet.RemoveAt(mSynchronizeData.needDownloadSet.Count - 1); string fileRelativePath = null; if (string.IsNullOrEmpty(downloadFileInfo.filePath)) { //服务器中是以MD5命名的。 fileRelativePath = downloadFileInfo.fileMd5; } else { fileRelativePath = Path.Combine(downloadFileInfo.filePath, downloadFileInfo.fileMd5); } string fileUrl = Path.Combine(mSynchronizeData.ServerDataPath, fileRelativePath); mDownloadId = GameMain.Instance.HttpMgr.DownLoad(fileUrl, delegate(byte[] fileBytes) { Logger.LogInfo("NewDownload download file success,name:" + downloadFileInfo.fileName + " url:" + fileUrl); if (downloadFileInfo.fileLength != fileBytes.Length) { mErrorHandler.Invoke(FileErrorCode.FileLengthError, fileUrl + " serverL:" + downloadFileInfo.fileLength + " realL:" + fileBytes.Length); } else { string md5 = Utils.MD5(fileBytes); if (md5 != downloadFileInfo.fileMd5) { mErrorHandler.Invoke(FileErrorCode.FileMd5Error, fileUrl + " serverMd5:" + downloadFileInfo.fileMd5 + " realMd5:" + md5); } else { string errorInfo; FileErrorCode errorCode = FileOperateUtils.TryFileWrite(delegate(){ string relativePath = FileSystemUtils.GetFileRelativePath(downloadFileInfo.fileName, downloadFileInfo.filePath, true); GameMain.Instance.FileOperateMgr.CreateDirIfNotExist(Path.GetDirectoryName(relativePath)); GameMain.Instance.FileOperateMgr.WriteBinaryFile(relativePath, fileBytes); }, out errorInfo); if (FileErrorCode.Null != errorCode) { mErrorHandler.Invoke(errorCode, errorInfo); } else { mSynchronizeData.persistentFileListDic.Add(downloadFileInfo.fileName, downloadFileInfo); errorCode = FileOperateUtils.TryFileWrite(delegate(){ string detailStr = FileListUtils.DetailInfoToString(downloadFileInfo); string relativePath = FileSystemUtils.GetFileRelativePath(FileDownloadData.FileListFileName, string.Empty); GameMain.Instance.FileOperateMgr.WriteTextFile(relativePath, detailStr, true); }, out errorInfo); if (FileErrorCode.Null != errorCode) { mErrorHandler.Invoke(errorCode, errorInfo); } else { mFinishFilesSize += (ulong)downloadFileInfo.fileLength; mCurFileSize = 0; DownLoadFile(); } } } } }, delegate(string errorCode) { Logger.LogError("NewDownload download file failed,name:" + downloadFileInfo.fileName + " url:" + fileUrl); mErrorHandler.Invoke(FileErrorCode.DownloadFileError, fileUrl); }, delegate(ulong curDownloadedBytes) { mCurFileSize = curDownloadedBytes; ShowTipInfo(); }); }