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);
|
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