/// <summary> /// 获取分卷文件的文件头结构 /// </summary> /// <param name="fs">文件流,调用此方法文件指针将会重置到文件起始位置</param> /// <returns></returns> public CutedFileHead GetCutedFileHead(FileStream fs) { fs.Seek(0, SeekOrigin.Begin); BinaryReader br = new BinaryReader(fs); CutedFileHead head = new CutedFileHead(); head.Flag = br.ReadInt32(); if (head.Flag == CUT_FILE_FLAG) { head.Offset = br.ReadInt32(); head.FileNumber = br.ReadInt16(); head.FileCount = br.ReadInt16(); int strLength = head.Offset - 2 * sizeof(int) - 2 * sizeof(short); head.FileName = System.Text.Encoding.Default.GetString(br.ReadBytes(strLength)); } else { head.FileName = "无效的分卷文件。"; } return(head); }
/// <summary> /// 链接文件。 /// </summary> /// <param name="cutedFiles">切分的文件名数组</param> /// <param name="descFolder">链接文件保存的目录,如果为空则采用第一个分卷文件所在的目录</param> /// <param name="descFileName">链接文件的名称,不带路径。如果为空,则采用链接文件中记录的原始文件名</param> /// <returns>链接后的文件名,如果操作不成功返回空</returns> public string Link(string[] cutedFiles, string descFolder, string descFileName) { this.ProgressWorking = true; this.CutedFiles = cutedFiles; CutedFileHead[] heads = new CutedFileHead[cutedFiles.Length]; //List<string> sortedFiles = null; if (!VerifyCutedFiles(cutedFiles, ref heads))//, out sortedFiles { return(""); } if (string.IsNullOrEmpty(descFolder)) { descFolder = System.IO.Path.GetDirectoryName(cutedFiles[0]); } else { if (!Directory.Exists(descFolder)) { Directory.CreateDirectory(descFolder); } } string sourceFileName = string.IsNullOrEmpty(descFileName) ? heads[0].FileName : descFileName; FileStream fsDesc = null;// try { fsDesc = File.Create(descFolder + "\\" + sourceFileName); //开始合并文件 for (int i = 0; i < heads.Length; i++) { this.ProgressFileName = heads[i].MapFileName; this.ProgresFileNumber = i; using (FileStream fsRead = new FileStream(heads[i].MapFileName, FileMode.Open, FileAccess.Read)) { this.ProgressFileSize = (int)fsRead.Length; //定位到文件的正文开头 fsRead.Seek(heads[i].Offset, SeekOrigin.Begin); int offset = 0; int readCount = 0; do { byte[] dataArray = new byte[SIZE]; readCount = fsRead.Read(dataArray, 0, SIZE); if (readCount == 0) { break; } //可以将 offset 作为进度条信息给外面使用,建议使用时钟定期查询 offset += readCount; this.ProgressFileRead = offset; //模拟大文件,正式版本请注释下面一行代码 //System.Threading.Thread.Sleep(10); //将当前块数据写入目标文件 fsDesc.Write(dataArray, 0, readCount); } while (readCount == SIZE); fsRead.Close(); fsRead.Dispose(); } }//end for //连接成功后删除源文件 if (this.DeleteFileArterLink) { for (int i = 0; i < heads.Length; i++) { File.Delete(heads[i].MapFileName); } } } catch (Exception ex) { this.ErrorMessage = ex.Message; } finally { if (fsDesc != null) { fsDesc.Close(); fsDesc.Dispose(); fsDesc = null; } } this.ProgressWorking = false; return(sourceFileName); }
/// <summary> /// 校验一组文件是否是有效的分组文件 /// </summary> /// <param name="cutedFiles">要检查的源分卷文件数组</param> /// <param name="heads">符合目标的文件头数组</param> /// <returns></returns> public bool VerifyCutedFiles(string[] cutedFiles, ref CutedFileHead[] heads)//, out List<string> sortedFiles { //sortedFiles = new List<string>(); this.ErrorMessage = ""; if (cutedFiles.Length <= 1) { this.ErrorMessage = "分卷文件需要至少2个。"; return(false); } //检查所有文件头信息 string checkMsg = ""; List <CutedFileHead> headList = new List <CutedFileHead>();//本次所有有效的文件头列表 for (int i = 0; i < cutedFiles.Length; i++) { CutedFileHead head = GetCutedFileHead(cutedFiles[i]); if (head.Flag != CUT_FILE_FLAG) { checkMsg += "\r\n当前文件不是有效的分卷文件:" + cutedFiles[i]; //将无效文件删除 File.Delete(cutedFiles[i]); } else { head.MapFileName = cutedFiles[i]; headList.Add(head); } } if (headList.Count <= 1) { //有效的分卷文件不够数量 this.ErrorMessage = "有效的分卷文件至少需要2个;" + checkMsg; return(false); } List <CutedFileHead> checkedHeads = new List <CutedFileHead>(); //验证有效的文件文件列表 var firstHeads = headList.FindAll(p => p.FileNumber == 1); //先找到第一个分卷文件,可能有多个(比如分次发送不同大小的文件) var foundOK = false; foreach (CutedFileHead item in firstHeads) { checkedHeads.Clear(); checkedHeads.Add(item); int fileCount = item.FileCount;//当前分卷文件对应的同类文件个数 for (int fileNumber = 2; fileNumber <= fileCount; fileNumber++) { var currtHeads = headList.FindAll(p => p.FileNumber == fileNumber && p.FileName == item.FileName).ToArray(); if (currtHeads.Length > 0) { //找到当前顺序的文件 checkedHeads.Add(currtHeads[0]); } else { //当前分卷文件不连续 break; } } if (checkedHeads.Count == item.FileCount) { //寻找到有效的文件头列表 foundOK = true; break; } } if (foundOK) { heads = checkedHeads.ToArray(); return(true); } else { this.ErrorMessage = "分卷文件不连续!"; return(false); } }