Read compressed elements without loading into memory
This commit is contained in:
parent
37feeb5863
commit
e8bf3f89ee
@ -343,30 +343,33 @@ namespace MatFileHandler
|
||||
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)
|
||||
{
|
||||
reader.ReadBytes(2);
|
||||
var compressedData = reader.ReadBytes(tag.Length - 6);
|
||||
reader.ReadBytes(4);
|
||||
var resultStream = new MemoryStream();
|
||||
using (var compressedStream = new MemoryStream(compressedData))
|
||||
|
||||
DataElement element;
|
||||
|
||||
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;
|
||||
return Read(resultStream);
|
||||
reader.ReadBytes(4);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
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