public void Init() { FileInfo fi = new FileInfo(_filename); if (!fi.Directory.Exists) { fi.Directory.Create(); } _fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); if (_fs.Length < SectorToByte(2)) { byte[] headByte = Enumerable.Repeat((byte)0x00, (int)SectorToByte(2)).ToArray(); _fs.Position = 0; _fs.Write(headByte, 0, headByte.Length); } _headData = new ChunkHeadData[REGION_WIDTH, REGION_DEPTH]; _useSector = new ArrayList(new bool[ByteToSector(_fs.Length)]); _useSector[0] = true; _useSector[1] = true; for (int x = 0; x < REGION_WIDTH; x++) { for (int z = 0; z < REGION_DEPTH; z++) { _headData[x, z] = new ChunkHeadData(x, z); ReadHeadData(x, z); } } _cs = new ChunkStream(); }
//获取到的块数据 public bool GetChunkData(int x, int z, Chunk chunk) { if (_headData[x, z].status == ChunkDataStatus.Not_Create) { return(false); } _fs.Position = SectorToByte(_headData[x, z].BlockOffset) + 5; _cs.SetLength(0); _cs.Write(_fs, _headData[x, z].Length); _cs.Position = 0; IMTBCompress compress = MTBCompressFactory.GetCompress(_headData[x, z].CompressionType); _cs = (ChunkStream)compress.Decompress(_cs); _cs.Position = 0; chunk.Deserialize(_cs); return(true); }
//保存块的字节数据 public void SaveChunkData(int x, int z, Chunk chunk) { _cs.SetLength(0); chunk.Serialize(_cs); _cs.Position = 0; IMTBCompress compress = MTBCompressFactory.GetCompress(_compressType); _cs = (ChunkStream)compress.Encompress(_cs); byte[] chunkSize = new byte[4]; Serialization.WriteIntToByteArr(chunkSize, (int)_cs.Length); int singleChunkLength = (int)_cs.Length + 5; int blockLength = ByteToSector(singleChunkLength); ClearChunkData(x, z); int blockOffset = GetChunkCanSavedSector(blockLength); long blockOffsetStartByteIndex = SectorToByte(blockOffset); _fs.Position = blockOffsetStartByteIndex; //写入区块长度 _fs.Write(chunkSize, 0, chunkSize.Length); //写入压缩格式 _fs.WriteByte((byte)compress.CompressType); //写入区块压缩数据 _cs.Position = 0; _cs.Read(_fs, (int)_cs.Length); int startPosition = (x * REGION_DEPTH + z) * 4; _fs.Position = startPosition; byte[] blockOffsetByte = new byte[4]; Serialization.WriteIntToByteArr(blockOffsetByte, blockOffset); _fs.Write(blockOffsetByte, 0, 3); _fs.WriteByte((byte)blockLength); //更新可存储标志,并将块后面不足一个扇区的部分写0x00 for (int i = blockOffset; i < blockOffset + blockLength; i++) { _useSector[i] = true; } long chunkEnd = blockOffsetStartByteIndex + singleChunkLength; long sectorEnd = blockOffsetStartByteIndex + SectorToByte(blockLength); if (chunkEnd < sectorEnd) { _fs.Position = chunkEnd; byte[] extendByte = Enumerable.Repeat((byte)0x00, (int)(sectorEnd - chunkEnd)).ToArray(); _fs.Write(extendByte, 0, extendByte.Length); } //截取文件最后没有使用的扇区 int lastUseSectorIndex = GetLastUseSectorIndex(); if (lastUseSectorIndex != -1 && lastUseSectorIndex != _useSector.Count - 1) { int truncatedIndex = lastUseSectorIndex + 1; _useSector.RemoveRange(truncatedIndex, _useSector.Count - truncatedIndex); _fs.SetLength(SectorToByte(truncatedIndex)); } //更新headData数据 _headData[x, z].BlockOffset = blockOffset; _headData[x, z].BlockLength = (byte)blockLength; _headData[x, z].Length = (int)_cs.Length; _headData[x, z].status = ChunkDataStatus.OK; _headData[x, z].CompressionType = compress.CompressType; }