public void RebuildFile(PatchPartContext part, string tempDir, string msDir) { this.OnPatchStart(part); string tempFileName = Path.Combine(tempDir, part.FileName); EnsureDirExists(tempFileName); part.OldFilePath = Path.Combine(msDir, part.FileName); this.OnVerifyOldChecksumBegin(part); FileStream oldWzFile = new FileStream(part.OldFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 0x4000, FileOptions.Asynchronous | FileOptions.RandomAccess); uint oldCheckSum1 = CheckSum.ComputeHash(oldWzFile, (int)oldWzFile.Length); //旧版本文件实际hash this.OnVerifyOldChecksumEnd(part); try { VerifyCheckSum(part.OldChecksum, oldCheckSum1, part.FileName, "origin"); } catch { if (oldWzFile.Length == part.NewFileLength && oldCheckSum1 == part.NewChecksum) //文件已更新的场合 { oldWzFile.Close(); return; } else { throw; } } int cmd; //int blockLength; FileStream tempFileStream = new FileStream(tempFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 0x4000); part.TempFilePath = tempFileName; if (part.NewFileLength > 0) //预申请硬盘空间 似乎可以加快读写速度 { tempFileStream.SetLength(part.NewFileLength); tempFileStream.Seek(0, SeekOrigin.Begin); } this.OnTempFileCreated(part); uint newCheckSum1 = 0; this.InflateStreamSeek(part.Offset); BinaryReader r = new BinaryReader(this.inflateStream); double patchProc = 0; const double patchProcReportInverval = 0.005; //v3新增读缓冲 List <RebuildFileOperation> operList = new List <RebuildFileOperation>(32768); List <RebuildFileOperation> readFileOperList = new List <RebuildFileOperation>(operList.Capacity); MemoryStream msBuffer = new MemoryStream(1024 * 1024 * 64); int preLoadByteCount = 0; while (true) { cmd = r.ReadInt32(); RebuildFileOperation op = null; if (cmd != 0) { switch ((uint)cmd >> 0x1C) { case 0x08: op = new RebuildFileOperation(0); op.Length = cmd & 0x0fffffff; break; case 0x0c: op = new RebuildFileOperation(1); op.FillByte = (byte)(cmd & 0xff); op.Length = (cmd & 0x0fffff00) >> 8; break; default: op = new RebuildFileOperation(2); op.Length = cmd; op.StartPosition = r.ReadInt32(); break; } } //如果大于 先处理当前所有预读操作 if (cmd == 0 || (operList.Count >= operList.Capacity - 1) || (op.OperType != 1 && (op.Length + preLoadByteCount > msBuffer.Capacity))) { //排序预读原文件 readFileOperList.Sort((first, second) => first.StartPosition.CompareTo(second.StartPosition)); foreach (var readFileOp in readFileOperList) { int position = (int)msBuffer.Position; readFileOp.Flush(oldWzFile, null, null, msBuffer); readFileOp.bufferStartIndex = position; } //向新文件输出 foreach (var tempOp in operList) { newCheckSum1 = tempOp.Flush(oldWzFile, r.BaseStream, msBuffer, tempFileStream, newCheckSum1); //计算更新进度 if (part.NewFileLength > 0) { double curProc = 1.0 * tempFileStream.Position / part.NewFileLength; if (curProc - patchProc >= patchProcReportInverval) // || curProc >= 1 - patchProcReportInverval) { this.OnTempFileUpdated(part, tempFileStream.Position); //更新进度改变 patchProc = curProc; } } else { if (tempFileStream.Position - patchProc > 1024 * 1024 * 10) { this.OnTempFileUpdated(part, tempFileStream.Position);//更新进度改变 patchProc = tempFileStream.Position; } } } //重置缓冲区 msBuffer.SetLength(0); preLoadByteCount = 0; operList.Clear(); readFileOperList.Clear(); if (cmd == 0) // 更新结束 这里是出口无误 { break; } } if (op.OperType != 1 && op.Length >= msBuffer.Capacity) //还是大于的话 单独执行 { newCheckSum1 = op.Flush(oldWzFile, r.BaseStream, null, tempFileStream, newCheckSum1); } else //直接放进缓冲区里 { op.Index = (ushort)operList.Count; operList.Add(op); switch (op.OperType) { case 0: int position = (int)msBuffer.Position; op.Flush(null, r.BaseStream, null, msBuffer); op.bufferStartIndex = position; break; case 1: continue; case 2: readFileOperList.Add(op); break; } preLoadByteCount += op.Length; } } msBuffer.Dispose(); msBuffer = null; tempFileStream.Flush(); tempFileStream.SetLength(tempFileStream.Position); //设置文件大小为当前长度 this.OnVerifyNewChecksumBegin(part); tempFileStream.Seek(0, SeekOrigin.Begin); //uint _newCheckSum1 = CheckSum.ComputeHash(tempFileStream, (int)tempFileStream.Length); //新生成文件的hash VerifyCheckSum(part.NewChecksum, newCheckSum1, part.FileName, "new"); this.OnVerifyNewChecksumEnd(part); oldWzFile.Close(); tempFileStream.Flush(); tempFileStream.Close(); this.OnTempFileClosed(part); }
public void RebuildFile(PatchPartContext part, string tempDir, string msDir) { this.OnPatchStart(part); string tempFileName = Path.Combine(tempDir, part.FileName); EnsureDirExists(tempFileName); part.OldFilePath = Path.Combine(msDir, part.FileName); var oldWzFiles = new Dictionary <string, FileStream>(); FileStream tempFileStream = null; FileStream openFile(string fileName) { if (string.IsNullOrEmpty(fileName)) { return(null); } if (!oldWzFiles.TryGetValue(fileName, out var fs)) { fs = new FileStream(Path.Combine(msDir, fileName), FileMode.Open, FileAccess.Read, FileShare.Read); oldWzFiles.Add(fileName, fs); } return(fs); } void closeAllFiles() { foreach (var fs in oldWzFiles.Values) { fs.Close(); } tempFileStream?.Close(); } try { if (this.IsKMST1125Format == true) { // skip old file checking } else if (part.OldChecksum != null) { var oldWzFile = openFile(part.FileName); this.OnVerifyOldChecksumBegin(part); uint oldCheckSum1 = CheckSum.ComputeHash(oldWzFile, oldWzFile.Length); //旧版本文件实际hash this.OnVerifyOldChecksumEnd(part); try { VerifyCheckSum(part.OldChecksum.Value, oldCheckSum1, part.FileName, "origin"); } catch { if (oldWzFile.Length == part.NewFileLength && oldCheckSum1 == part.NewChecksum) //文件已更新的场合 { oldWzFile.Close(); return; } else { throw; } } } int cmd; //int blockLength; tempFileStream = new FileStream(tempFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 0x4000); part.TempFilePath = tempFileName; if (part.NewFileLength > 0) //预申请硬盘空间 似乎可以加快读写速度 { tempFileStream.SetLength(part.NewFileLength); tempFileStream.Seek(0, SeekOrigin.Begin); } this.OnTempFileCreated(part); uint newCheckSum1 = 0; this.InflateStreamSeek(part.Offset); BinaryReader r = new BinaryReader(this.inflateStream); double patchProc = 0; const double patchProcReportInverval = 0.005; //v3新增读缓冲 List <RebuildFileOperation> operList = new List <RebuildFileOperation>(32768); List <RebuildFileOperation> readFileOperList = new List <RebuildFileOperation>(operList.Capacity); MemoryStream msBuffer = new MemoryStream(1024 * 1024 * 64); int preLoadByteCount = 0; while (true) { cmd = r.ReadInt32(); RebuildFileOperation op = null; if (cmd != 0) { switch ((uint)cmd >> 0x1C) { case 0x08: op = new RebuildFileOperation(0); op.Length = cmd & 0x0fffffff; break; case 0x0c: op = new RebuildFileOperation(1); op.FillByte = (byte)(cmd & 0xff); op.Length = (cmd & 0x0fffff00) >> 8; break; default: op = new RebuildFileOperation(2); op.Length = cmd; op.StartPosition = r.ReadInt32(); op.FromFileName = this.IsKMST1125Format.Value ? this.ReadStringWithLength(r) : part.FileName; break; } } //如果大于 先处理当前所有预读操作 if (cmd == 0 || (operList.Count >= operList.Capacity - 1) || (op.OperType != 1 && (op.Length + preLoadByteCount > msBuffer.Capacity))) { //排序预读原文件 readFileOperList.Sort((left, right) => { int cmp; if ((cmp = string.Compare(left.FromFileName, right.FromFileName, StringComparison.OrdinalIgnoreCase)) != 0) { return(cmp); } return(left.StartPosition.CompareTo(right.StartPosition)); }); foreach (var readFileOp in readFileOperList) { int position = (int)msBuffer.Position; readFileOp.Flush(openFile(readFileOp.FromFileName), null, null, msBuffer); readFileOp.bufferStartIndex = position; } //向新文件输出 foreach (var tempOp in operList) { newCheckSum1 = tempOp.Flush(openFile(tempOp.FromFileName), r.BaseStream, msBuffer, tempFileStream, newCheckSum1); //计算更新进度 if (part.NewFileLength > 0) { double curProc = 1.0 * tempFileStream.Position / part.NewFileLength; if (curProc - patchProc >= patchProcReportInverval) // || curProc >= 1 - patchProcReportInverval) { this.OnTempFileUpdated(part, tempFileStream.Position); //更新进度改变 patchProc = curProc; } } else { if (tempFileStream.Position - patchProc > 1024 * 1024 * 10) { this.OnTempFileUpdated(part, tempFileStream.Position);//更新进度改变 patchProc = tempFileStream.Position; } } } //重置缓冲区 msBuffer.SetLength(0); preLoadByteCount = 0; operList.Clear(); readFileOperList.Clear(); if (cmd == 0) // 更新结束 这里是出口无误 { break; } } if (op.OperType != 1 && op.Length >= msBuffer.Capacity) //还是大于的话 单独执行 { newCheckSum1 = op.Flush(openFile(op.FromFileName), r.BaseStream, null, tempFileStream, newCheckSum1); } else //直接放进缓冲区里 { op.Index = (ushort)operList.Count; operList.Add(op); switch (op.OperType) { case 0: int position = (int)msBuffer.Position; op.Flush(null, r.BaseStream, null, msBuffer); op.bufferStartIndex = position; break; case 1: continue; case 2: readFileOperList.Add(op); break; } preLoadByteCount += op.Length; } } msBuffer.Dispose(); msBuffer = null; tempFileStream.Flush(); tempFileStream.SetLength(tempFileStream.Position); //设置文件大小为当前长度 closeAllFiles(); this.OnVerifyNewChecksumBegin(part); //tempFileStream.Seek(0, SeekOrigin.Begin); //uint _newCheckSum1 = CheckSum.ComputeHash(tempFileStream, (int)tempFileStream.Length); //新生成文件的hash VerifyCheckSum(part.NewChecksum, newCheckSum1, part.FileName, "new"); this.OnVerifyNewChecksumEnd(part); this.OnTempFileClosed(part); } finally { closeAllFiles(); } }