/// <summary> /// Open file by hash /// </summary> /// <param name="hash"></param> /// <returns>file stream</returns> /// <exception cref="FileNotFoundException"></exception> public DecimaCoreFile OpenFile(long hash) { if (!RecordTableByHash.TryGetValue(hash, out var recordIndex)) { throw new FileNotFoundException($"Cannot find hash {hash:X16}"); } var record = RecordTable[(int)recordIndex]; var(chunk, index) = BlockTable.Select((x, y) => new KeyValuePair <DecimaCacheBlockTableEntry, int>(x, y)).First(x => { var(key, _) = x; return(key.ChunkOffset + key.ChunkSize > record.Offset); }); var buffer = new MemoryStream(record.Size); while (buffer.Position < record.Size) { var block = OpenBlock(chunk); var start = 0; if (chunk.ChunkOffset < record.Offset) { start = (int)(record.Offset - chunk.ChunkOffset); } var end = block.Length - start; if (end + buffer.Position > record.Size) { end = (int)(record.Size - buffer.Position); } buffer.Write(block.Slice(start, end)); index += 1; if (index >= BlockTable.Count) { break; } chunk = BlockTable[index]; } // Debug.Assert(buffer.Length == record.Size, "buffer.Length == record.Size"); buffer.Position = 0; return(new DecimaCoreFile(buffer)); }