Read compressed elements without loading into memory #34
@ -343,30 +343,33 @@ namespace MatFileHandler
 | 
				
			|||||||
            return new MatStructureArray(flags, dimensions, name, fields);
 | 
					            return new MatStructureArray(flags, dimensions, name, fields);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private DataElement Read(Stream stream)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            using (var reader = new BinaryReader(stream))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return Read(reader);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private DataElement ReadCompressed(Tag tag, BinaryReader reader)
 | 
					        private DataElement ReadCompressed(Tag tag, BinaryReader reader)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            reader.ReadBytes(2);
 | 
					            reader.ReadBytes(2);
 | 
				
			||||||
            var compressedData = reader.ReadBytes(tag.Length - 6);
 | 
					
 | 
				
			||||||
            reader.ReadBytes(4);
 | 
					            DataElement element;
 | 
				
			||||||
            var resultStream = new MemoryStream();
 | 
					
 | 
				
			||||||
            using (var compressedStream = new MemoryStream(compressedData))
 | 
					            using (var substream = new Substream(reader.BaseStream, tag.Length - 6))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                using (var stream = new DeflateStream(compressedStream, CompressionMode.Decompress, leaveOpen: true))
 | 
					                using (var deflateStream = new DeflateStream(substream, CompressionMode.Decompress))
 | 
				
			||||||
 | 
					                using (var bufferedStream = new BufferedStream(deflateStream))
 | 
				
			||||||
 | 
					                using (var positionTrackingStream = new PositionTrackingStream(bufferedStream))
 | 
				
			||||||
 | 
					                using (var innerReader = new BinaryReader(positionTrackingStream))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    stream.CopyTo(resultStream);
 | 
					                    element = Read(innerReader);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (substream.Position != substream.Length)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // In the pathological case that the deflate stream did not read the full
 | 
				
			||||||
 | 
					                    // length, then read out the rest manually (normally 1 byte).
 | 
				
			||||||
 | 
					                    reader.ReadBytes((int)(substream.Length - substream.Position));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            resultStream.Position = 0;
 | 
					            reader.ReadBytes(4);
 | 
				
			||||||
            return Read(resultStream);
 | 
					
 | 
				
			||||||
 | 
					            return element;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private DataElement ReadMatrix(Tag tag, BinaryReader reader)
 | 
					        private DataElement ReadMatrix(Tag tag, BinaryReader reader)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										68
									
								
								MatFileHandler/Substream.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								MatFileHandler/Substream.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					// Copyright 2017-2018 Alexander Luzgarev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MatFileHandler
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// A stream which reads a finite section of another stream.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    internal sealed class Substream : Stream
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly Stream _baseStream;
 | 
				
			||||||
 | 
					        private long _bytesRead;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes a new instance of the <see cref="Substream"/> class.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="baseStream">The <see cref="Stream"/> to wrap.</param>
 | 
				
			||||||
 | 
					        /// <param name="length">The number of bytes readable from this <see cref="Substream"/>.</param>
 | 
				
			||||||
 | 
					        public Substream(Stream baseStream, long length)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _baseStream = baseStream;
 | 
				
			||||||
 | 
					            Length = length;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override bool CanRead => _baseStream.CanRead;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override bool CanSeek => false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override bool CanWrite => false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override long Length { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override long Position
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get => _bytesRead;
 | 
				
			||||||
 | 
					            set => throw new NotSupportedException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override void Flush() => _baseStream.Flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override int Read(byte[] buffer, int offset, int count)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int bytesRead = _baseStream.Read(buffer, offset, (int)Math.Min(count, Length - _bytesRead));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _bytesRead += bytesRead;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return bytesRead;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
 | 
					        public override void SetLength(long value) => throw new NotSupportedException();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user