private void SaveFile(string filename, bool enableNewCode = true) { using (FileStream strWriter = new FileStream(filename, System.IO.FileMode.Create)) { UInt32 stElemSize = stElemAddr.Size(); UInt32 ElemsNum = (UInt32)Elems.Count; UInt32 cur_block_addr = stFileHeader.Size() + stBlockHeader.Size(); if (stElemAddr.Size() * ElemsNum < V8_DEFAULT_PAGE_SIZE) cur_block_addr += V8_DEFAULT_PAGE_SIZE; // 512 - стандартный размер страницы 0x200 else cur_block_addr += stElemAddr.Size() * ElemsNum; byte[] pTempElemsAddrs = new byte[Elems.Count * stElemSize]; foreach (CV8Elem elem in Elems) { int elIndex = Elems.IndexOf(elem); stElemAddr curAddr = new stElemAddr(); curAddr.elem_header_addr = cur_block_addr; cur_block_addr += stBlockHeader.Size() + elem.HeaderSize; curAddr.elem_data_addr = cur_block_addr; cur_block_addr += stBlockHeader.Size(); if (elem.DataSize > V8_DEFAULT_PAGE_SIZE) cur_block_addr += elem.DataSize; else cur_block_addr += V8_DEFAULT_PAGE_SIZE; curAddr.fffffff = 0x7fffffff; byte[] tmpAddrBytes = curAddr.ToBytes(); Array.Copy(tmpAddrBytes, 0, pTempElemsAddrs, elIndex * stElemSize, stElemSize); } UInt32 cur_pos = 0; // записываем заголовок strWriter.Write(FileHeader.ToBytes(), 0, (int)stFileHeader.Size()); cur_pos += stFileHeader.Size(); // записываем адреса элементов byte[] buffer; if (pTempElemsAddrs.Length < V8_DEFAULT_PAGE_SIZE) { buffer = new byte[V8_DEFAULT_PAGE_SIZE + stBlockHeader.Size()]; } else { buffer = new byte[pTempElemsAddrs.Length + stBlockHeader.Size()]; } UInt32 bufCurPos = 0; SaveBlockDataToBuffer(ref buffer, ref bufCurPos, pTempElemsAddrs); strWriter.Write(buffer, 0, buffer.Length); cur_pos += bufCurPos; // записываем элементы (заголовок и данные) foreach (CV8Elem elem in Elems) { using (MemoryTributary memBuffer = new MemoryTributary()) { BinaryWriter binMemBuffer = new BinaryWriter(memBuffer); memBuffer.Position = 0; SaveBlockDataToBuffer(ref binMemBuffer, elem.GetHeaderLikeMemStream(), elem.HeaderSize); // Переносим данные из memBuffer в файл binMemBuffer.BaseStream.Position = 0; for (int i = 0; i < binMemBuffer.BaseStream.Length; i++) { strWriter.WriteByte(Convert.ToByte(binMemBuffer.BaseStream.ReadByte())); } } using (MemoryTributary memBuffer = new MemoryTributary()) { BinaryWriter binMemBuffer = new BinaryWriter(memBuffer); memBuffer.Position = 0; bufCurPos = 0; SaveBlockDataToBuffer(ref binMemBuffer, elem.GetDataLikeMemStream()); cur_pos += bufCurPos; // Переносим данные из memBuffer в файл binMemBuffer.BaseStream.Position = 0; for (int i = 0; i < binMemBuffer.BaseStream.Length; i++) { strWriter.WriteByte(Convert.ToByte(binMemBuffer.BaseStream.ReadByte())); } } } } }
private void LoadFile(BinaryReader inputFileStream, bool boolInflate = true, bool UnpackWhenNeed = true) { long prevPosition = inputFileStream.BaseStream.Position; inputFileStream.BaseStream.Position = 0; bool useTempFiles = false; if(OperationMode == Mode.FileSystem) useTempFiles = true; else if (OperationMode == Mode.Optimal) { // В оптимальном режиме, если обрабатываемый файл больше 200 МБ, // то автоматически включается режим использования файловой системы if (inputFileStream.BaseStream.Length > MAX_FILE_SIZE) OperationMode = Mode.FileSystem; } MemoryTributary InflateBufferStream; UInt32 InflateSize = 0; this.FileHeader = new stFileHeader(inputFileStream.ReadBytes((int)stFileHeader.Size()), 0); stBlockHeader pBlockHeader = new stBlockHeader(inputFileStream.ReadBytes((int)stBlockHeader.Size()), 0); UInt32 ElemsAddrsSize; MemoryTributary pElemsAddrsStream; ReadBlockData(inputFileStream, pBlockHeader, stFileHeader.Size(), out pElemsAddrsStream, out ElemsAddrsSize); UInt32 ElemsNum = ElemsAddrsSize / stElemAddr.Size(); Elems.Clear(); ElemsAddrs.Clear(); for (UInt32 i = 0; i < ElemsNum; i++) { stElemAddr pElemsAddrs = new stElemAddr(pElemsAddrsStream, (int)(i * stElemAddr.Size())); ElemsAddrs.Add(pElemsAddrs); if (pElemsAddrs.fffffff != V8_FF_SIGNATURE) { ElemsNum = i; break; } inputFileStream.BaseStream.Position = pElemsAddrs.elem_header_addr; pBlockHeader = new stBlockHeader(inputFileStream.ReadBytes((int)stBlockHeader.Size()), 0); if (pBlockHeader.EOL_0D != 0x0d || pBlockHeader.EOL_0A != 0x0a || pBlockHeader.space1 != 0x20 || pBlockHeader.space2 != 0x20 || pBlockHeader.space3 != 0x20 || pBlockHeader.EOL2_0D != 0x0d || pBlockHeader.EOL2_0A != 0x0a) { throw new Exception("Header is not correct!"); } UInt32 ElemsAddrsSizeHeader = 0; MemoryTributary pHeaderStream; UInt32 DataSize = 0; MemoryTributary pDataStream; ReadBlockData(inputFileStream, pBlockHeader, pElemsAddrs.elem_header_addr, out pHeaderStream, out ElemsAddrsSizeHeader); //080228 Блока данных может не быть, тогда адрес блока данных равен 0x7fffffff if (pElemsAddrs.elem_data_addr != V8_FF_SIGNATURE) { inputFileStream.BaseStream.Position = pElemsAddrs.elem_data_addr; pBlockHeader = new stBlockHeader(inputFileStream.ReadBytes((int)stBlockHeader.Size()), 0); ReadBlockData(inputFileStream, pBlockHeader, pElemsAddrs.elem_data_addr, out pDataStream, out DataSize); } else { throw new Exception("Incorrect data block!"); } CV8Elem elem = new CV8Elem(pHeaderStream, ElemsAddrsSizeHeader, pDataStream, (UInt32)pDataStream.Length, this, false, false, useTempFiles); if (boolInflate && IsDataPacked) { bool success = Inflate(elem.GetDataLikeMemStream(), out InflateBufferStream); if (!success) { IsDataPacked = false; elem.SetDataFromMemStream(InflateBufferStream); elem.DataSize = (UInt32)InflateBufferStream.Length; elem.IsV8File = false; } else { elem.NeedUnpack = false; // отложенная распаковка не нужна elem.pData = null; //нераспакованные данные больше не нужны if (IsV8File(InflateBufferStream)) { elem.UnpackedData = new V8File(this, InflateBufferStream, (int)InflateSize, boolInflate, this.OperationMode); elem.pData = null; elem.IsV8File = true; } else { elem.SetDataFromMemStream(InflateBufferStream); elem.DataSize = InflateSize; elem.IsV8File = false; } } } elem.InitElemName(inputFileStream, pElemsAddrs); Elems.Add(elem); } inputFileStream.BaseStream.Position = prevPosition; }
public void InitElemName(BinaryReader inputFileStream, stElemAddr ElemAddr) { this.elemNameLen = (ElemAddr.elem_data_addr - 4 - ElemAddr.elem_header_addr - stBlockHeader.Size() - stElemHeaderBegin.Size()) / 2; char[] invalidChars = Path.GetInvalidFileNameChars(); char[] ElemName = new char[0]; char[] ElemNameBuf = new char[this.elemNameLen]; int validChars = 0; for (UInt32 j = 0; j < this.elemNameLen * 2; j += 2) { inputFileStream.BaseStream.Position = j + ElemAddr.elem_header_addr + stBlockHeader.Size() + stElemHeaderBegin.Size(); char curChar = Convert.ToChar(inputFileStream.ReadByte()); if (invalidChars.Where(ch => ch == curChar).Count() != 0) { ElemName = new char[validChars]; break; } ElemNameBuf[j / 2] = curChar; validChars++; } if (ElemName.Length != 0) { for (int i = 0; i < ElemName.Length; i++) ElemName[i] = ElemNameBuf[i]; } else { ElemName = ElemNameBuf; } this.elemName = new string(ElemName); }
private void GetData(out MemoryTributary dataStream) { UInt32 stElemSize = stElemAddr.Size(); UInt32 NeedDataBufferSize = 0; NeedDataBufferSize += stFileHeader.Size(); // заголовок блока и данные блока - адреса элементов с учетом минимальной страницы 512 байт NeedDataBufferSize += stBlockHeader.Size() + (UInt32)Math.Max(stElemSize * Elems.Count, V8_DEFAULT_PAGE_SIZE); foreach (CV8Elem elem in Elems) { // заголовок блока и данные блока - заголовок элемента NeedDataBufferSize += stBlockHeader.Size() + elem.HeaderSize; // заголовок блока и данные блока - данные элемента с учетом минимальной страницы 512 байт NeedDataBufferSize += stBlockHeader.Size() + (UInt32)Math.Max(elem.DataSize, V8_DEFAULT_PAGE_SIZE); } // Создаем и заполняем данные по адресам элементов byte[] pTempElemsAddrs = new byte[Elems.Count * stElemSize]; UInt32 cur_block_addr = stFileHeader.Size() + stBlockHeader.Size(); if (stElemSize * Elems.Count < V8_DEFAULT_PAGE_SIZE) cur_block_addr += V8_DEFAULT_PAGE_SIZE; // 512 - стандартный размер страницы 0x200 else cur_block_addr += stElemSize * (UInt32)Elems.Count; foreach (CV8Elem elem in Elems) { UInt32 elNum = (UInt32)Elems.IndexOf(elem); stElemAddr tmpAdrr = new stElemAddr(); tmpAdrr.elem_header_addr = cur_block_addr; cur_block_addr += stBlockHeader.Size() + elem.HeaderSize; tmpAdrr.elem_data_addr = cur_block_addr; cur_block_addr += stBlockHeader.Size(); if (elem.DataSize > V8_DEFAULT_PAGE_SIZE) cur_block_addr += elem.DataSize; else cur_block_addr += V8_DEFAULT_PAGE_SIZE; tmpAdrr.fffffff = 0x7fffffff; byte[] tmpAddrBytes = tmpAdrr.ToBytes(); Array.Copy(tmpAddrBytes, 0, pTempElemsAddrs, elNum * stElemSize, stElemSize); } dataStream = new MemoryTributary(); dataStream.SetLength(NeedDataBufferSize); BinaryWriter dataStreamBin = new BinaryWriter(dataStream); //DataBuffer = new byte[NeedDataBufferSize]; UInt32 cur_pos = 0; // записываем заголовок byte[] fileHeader = FileHeader.ToBytes(); dataStreamBin.Write(fileHeader); //Array.Copy(fileHeader, 0, DataBuffer, cur_pos, fileHeader.Length); cur_pos += stFileHeader.Size(); // записываем адреса элементов SaveBlockDataToBuffer(ref dataStreamBin, ref cur_pos, pTempElemsAddrs); // записываем элементы (заголовок и данные) foreach (CV8Elem elem in Elems) { SaveBlockDataToBuffer(ref dataStreamBin, ref cur_pos, elem.pHeader, elem.HeaderSize); SaveBlockDataToBuffer(ref dataStreamBin, ref cur_pos, elem.pData); } pTempElemsAddrs = null; }
byte[] GetBinaryOfFile() { using (MemoryStream strWriter = new MemoryStream()) { UInt32 stElemSize = stElemAddr.Size(); UInt32 ElemsNum = (UInt32)Elems.Count; UInt32 cur_block_addr = stFileHeader.Size() + stBlockHeader.Size(); if (stElemAddr.Size() * ElemsNum < V8_DEFAULT_PAGE_SIZE) cur_block_addr += V8_DEFAULT_PAGE_SIZE; // 512 - стандартный размер страницы 0x200 else cur_block_addr += stElemAddr.Size() * ElemsNum; byte[] pTempElemsAddrs = new byte[Elems.Count * stElemSize]; foreach (CV8Elem elem in Elems) { int elIndex = Elems.IndexOf(elem); stElemAddr curAddr = new stElemAddr(); curAddr.elem_header_addr = cur_block_addr; cur_block_addr += stBlockHeader.Size() + elem.HeaderSize; curAddr.elem_data_addr = cur_block_addr; cur_block_addr += stBlockHeader.Size(); if (elem.DataSize > V8_DEFAULT_PAGE_SIZE) cur_block_addr += elem.DataSize; else cur_block_addr += V8_DEFAULT_PAGE_SIZE; curAddr.fffffff = 0x7fffffff; byte[] tmpAddrBytes = curAddr.ToBytes(); Array.Copy(tmpAddrBytes, 0, pTempElemsAddrs, elIndex * stElemSize, stElemSize); } UInt32 cur_pos = 0; // записываем заголовок strWriter.Write(FileHeader.ToBytes(), 0, (int)stFileHeader.Size()); cur_pos += stFileHeader.Size(); // записываем адреса элементов byte[] buffer; if (pTempElemsAddrs.Length < V8_DEFAULT_PAGE_SIZE) { buffer = new byte[V8_DEFAULT_PAGE_SIZE + stBlockHeader.Size()]; } else { buffer = new byte[pTempElemsAddrs.Length + stBlockHeader.Size()]; } UInt32 bufCurPos = 0; SaveBlockDataToBuffer(ref buffer, ref bufCurPos, pTempElemsAddrs); strWriter.Write(buffer, 0, buffer.Length); cur_pos += bufCurPos; // записываем элементы (заголовок и данные) foreach (CV8Elem elem in Elems) { buffer = new byte[elem.HeaderSize + stBlockHeader.Size()]; bufCurPos = 0; SaveBlockDataToBuffer(ref buffer, ref bufCurPos, elem.pHeader, elem.HeaderSize); strWriter.Write(buffer, 0, buffer.Length); cur_pos += bufCurPos; if (elem.DataSize < V8_DEFAULT_PAGE_SIZE) { buffer = new byte[V8_DEFAULT_PAGE_SIZE + stBlockHeader.Size()]; } else { buffer = new byte[elem.DataSize + stBlockHeader.Size()]; } bufCurPos = 0; SaveBlockDataToBuffer(ref buffer, ref bufCurPos, elem.pData); strWriter.Write(buffer, 0, buffer.Length); cur_pos += bufCurPos; } return strWriter.ToArray(); } }
int LoadFile(byte[] pFileData, int FileDataSize, bool boolInflate = true, bool UnpackWhenNeed = true) { int ret = 0; if (pFileData.Length == 0) { return V8UNPACK_ERROR; } bool isV8File = IsV8File(pFileData, FileDataSize); if (!isV8File) { return V8UNPACK_NOT_V8_FILE; } byte[] InflateBuffer = new byte[0]; UInt32 InflateSize = 0; this.FileHeader = new stFileHeader(pFileData, 0); stBlockHeader pBlockHeader = new stBlockHeader(pFileData, stFileHeader.Size()); UInt32 ElemsAddrsSize; byte[] pElemsAddrsBytes; ReadBlockData(pFileData, pBlockHeader, stFileHeader.Size(), out pElemsAddrsBytes, out ElemsAddrsSize); UInt32 ElemsNum = ElemsAddrsSize / stElemAddr.Size(); Elems.Clear(); ElemsAddrs.Clear(); for (UInt32 i = 0; i < ElemsNum; i++) { stElemAddr pElemsAddrs = new stElemAddr(pElemsAddrsBytes, (int)(i * stElemAddr.Size())); ElemsAddrs.Add(pElemsAddrs); if (pElemsAddrs.fffffff != V8_FF_SIGNATURE) { ElemsNum = i; break; } pBlockHeader = new stBlockHeader(pFileData, pElemsAddrs.elem_header_addr); if (pBlockHeader.EOL_0D != 0x0d || pBlockHeader.EOL_0A != 0x0a || pBlockHeader.space1 != 0x20 || pBlockHeader.space2 != 0x20 || pBlockHeader.space3 != 0x20 || pBlockHeader.EOL2_0D != 0x0d || pBlockHeader.EOL2_0A != 0x0a) { ret = V8UNPACK_HEADER_ELEM_NOT_CORRECT; break; } UInt32 ElemsAddrsSizeHeader = 0; byte[] pElemsAddrsBytesHeader = new byte[0]; UInt32 DataSize = 0; byte[] pData = new byte[0]; ReadBlockData(pFileData, pBlockHeader, pElemsAddrs.elem_header_addr, out pElemsAddrsBytesHeader, out ElemsAddrsSizeHeader); //080228 Блока данных может не быть, тогда адрес блока данных равен 0x7fffffff if (pElemsAddrs.elem_data_addr != V8_FF_SIGNATURE) { pBlockHeader = new stBlockHeader(pFileData, pElemsAddrs.elem_data_addr); ReadBlockData(pFileData, pBlockHeader, pElemsAddrs.elem_data_addr, out pData, out DataSize); } else { throw new Exception("Ебать копать!!!"); //ReadBlockData(pFileData, null, out pData, out DataSize); } CV8Elem elem = new CV8Elem(pElemsAddrsBytesHeader, ElemsAddrsSizeHeader, pData, (UInt32)pData.Length, new V8Formats.V8File(), false, false); if (boolInflate && IsDataPacked) { ret = Inflate(pData, out InflateBuffer, DataSize, out InflateSize); if (ret != 0) { IsDataPacked = false; elem.pData = new byte[InflateSize]; elem.DataSize = InflateSize; InflateBuffer.CopyTo(elem.pData, 0); elem.IsV8File = false; } else { elem.NeedUnpack = false; // отложенная распаковка не нужна elem.pData = null; //нераспакованные данные больше не нужны if (IsV8File(InflateBuffer, (int)InflateSize)) { elem.UnpackedData = new V8File(InflateBuffer, (int)InflateSize, boolInflate); elem.pData = null; elem.IsV8File = true; } else { elem.pData = new byte[InflateSize]; elem.DataSize = InflateSize; InflateBuffer.CopyTo(elem.pData, 0); elem.IsV8File = false; } ret = 0; } } elem.InitElemName(pFileData, pElemsAddrs); Elems.Add(elem); } if (InflateBuffer.Length != 0) InflateBuffer = new byte[0]; return ret; }