Skip to content

Commit

Permalink
Merge pull request #55 from dbuenor/dbueno/feature-add-gzipstream-ex-…
Browse files Browse the repository at this point in the history
…to-framework

Added GZipStreamEx
  • Loading branch information
pruiz committed Aug 6, 2021
2 parents a170e86 + b9dfd54 commit 4a5c021
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 0 deletions.
1 change: 1 addition & 0 deletions HermaFx.Foundation/HermaFx.Foundation.csproj
Expand Up @@ -68,6 +68,7 @@
<Compile Include="Globalization\Currency.cs" />
<Compile Include="Guard.cs" />
<Compile Include="Guard.Expressions.cs" />
<Compile Include="IO\GZipStreamEx.cs" />
<Compile Include="Reflection\Accessor.cs" />
<Compile Include="Reflection\DummyPropertyInfo.cs" />
<Compile Include="Reflection\PropertyChain.cs" />
Expand Down
141 changes: 141 additions & 0 deletions HermaFx.Foundation/IO/GZipStreamEx.cs
@@ -0,0 +1,141 @@
using System;
using System.IO;
using System.IO.Compression;

namespace HermaFx.IO
{
public class GZipStreamEx : Stream
{
#region constructor / cleanup

public GZipStreamEx(Stream inputStream, uint internalBufferSize, CompressionLevel compressionLevel = CompressionLevel.Fastest)
{
try
{
_inputStream = inputStream;
_outputStream = new MemoryStream((int)internalBufferSize);
_gZipStream = new GZipStream(_outputStream, compressionLevel, true);
}
catch
{
Cleanup();
throw;
}
}

private void Cleanup()
{
_gZipStream?.Dispose();
_outputStream?.Dispose();
_inputStream?.Dispose();
}

#endregion

#region private variables

private bool _endOfInputStreamReached = false;

private readonly Stream _inputStream;
private readonly MemoryStream _outputStream;
private readonly GZipStream _gZipStream;

#endregion

#region stream overrides

public override bool CanRead => true;

public override bool CanSeek => false;

public override bool CanWrite => false;

public override long Length => 0;

public override long Position
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}

public override void SetLength(long value)
{
throw new NotSupportedException();
}

public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}

public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}

public override void Flush()
{
throw new NotSupportedException();
}

public override int Read(byte[] buffer, int offset, int count)
{
// 4k buffer size
var bufLength = count <= 4096 ? count : count / 4;
var buf = new byte[bufLength];

while ((_outputStream.Length < count) && !_endOfInputStreamReached)
{
var readCount = _inputStream.Read(buf, 0, buf.Length);
if (readCount == 0)
{
_endOfInputStreamReached = true;
_gZipStream.Flush();
_gZipStream.Dispose(); // because Flush() does not actually flush...
break;
}
else
{
_gZipStream.Write(buf, 0, readCount);
}
}

_outputStream.Position = 0;

var bytesRead = _outputStream.Read(buffer, offset, count);

if (_outputStream.Length > bytesRead)
{
// First we calculate how many bytes we should move to beggining.
var _remainingBytes = _outputStream.Length - bytesRead;
// We copy those remaining bytes to buf byte array.
_outputStream.Read(buf, 0, (int)_remainingBytes);
// We truncate outputStream to 0 length and set position to 0
_outputStream.SetLength(0);
// Then we copy those bytes to the 0 position for stream
_outputStream.Write(buf, 0, (int)_remainingBytes);
}
else
{
// We truncate outputStream to 0 length and set position to 0
_outputStream.SetLength(0);
}

return bytesRead;
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
Cleanup();
}
#endregion
}
}

0 comments on commit 4a5c021

Please sign in to comment.