11using System ;
2+ using System . Collections . Generic ;
23using System . IO ;
34using System . Linq ;
45using static LiteDB . Constants ;
@@ -7,9 +8,14 @@ namespace LiteDB
78{
89 public partial class LiteFileStream < TFileId > : Stream
910 {
11+ private Dictionary < int , long > _chunkLengths = new Dictionary < int , long > ( ) ;
1012 public override int Read ( byte [ ] buffer , int offset , int count )
1113 {
1214 if ( _mode != FileAccess . Read ) throw new NotSupportedException ( ) ;
15+ if ( _streamPosition == Length )
16+ {
17+ return 0 ;
18+ }
1319
1420 var bytesLeft = count ;
1521
@@ -42,23 +48,54 @@ private byte[] GetChunkData(int index)
4248 . FindOne ( "_id = { f: @0, n: @1 }" , _fileId , index ) ;
4349
4450 // if chunk is null there is no more chunks
45- return chunk ? [ "data" ] . AsBinary ;
51+ byte [ ] result = chunk ? [ "data" ] . AsBinary ;
52+ if ( result != null )
53+ {
54+ _chunkLengths [ index ] = result . Length ;
55+ }
56+ return result ;
4657 }
4758
4859 private void SetReadStreamPosition ( long newPosition )
4960 {
50- if ( newPosition < 0 && newPosition > Length )
61+ if ( newPosition < 0 )
5162 {
5263 throw new ArgumentOutOfRangeException ( ) ;
5364 }
65+ if ( newPosition >= Length )
66+ {
67+ _streamPosition = Length ;
68+ return ;
69+ }
5470 _streamPosition = newPosition ;
5571
5672 // calculate new chunk position
57- _currentChunkIndex = ( int ) _streamPosition / MAX_CHUNK_SIZE ;
58- _positionInChunk = ( int ) _streamPosition % MAX_CHUNK_SIZE ;
59-
60- // get current chunk
61- _currentChunkData = this . GetChunkData ( _currentChunkIndex ) ;
73+ long seekStreamPosition = 0 ;
74+ int loadedChunk = _currentChunkIndex ;
75+ int newChunkIndex = 0 ;
76+ while ( seekStreamPosition <= _streamPosition )
77+ {
78+ if ( _chunkLengths . TryGetValue ( newChunkIndex , out long length ) )
79+ {
80+ seekStreamPosition += length ;
81+ }
82+ else
83+ {
84+ loadedChunk = newChunkIndex ;
85+ _currentChunkData = GetChunkData ( newChunkIndex ) ;
86+ seekStreamPosition += _currentChunkData . Length ;
87+ }
88+ newChunkIndex ++ ;
89+ }
90+
91+ newChunkIndex -- ;
92+ seekStreamPosition -= _chunkLengths [ newChunkIndex ] ;
93+ _positionInChunk = ( int ) ( _streamPosition - seekStreamPosition ) ;
94+ _currentChunkIndex = newChunkIndex ;
95+ if ( loadedChunk != _currentChunkIndex )
96+ {
97+ _currentChunkData = GetChunkData ( _currentChunkIndex ) ;
98+ }
6299 }
63100 }
64101}
0 commit comments