HashingStream Class
Definition
Provides a pass-through Stream that feeds every byte read from or written to an inner stream into a NonCryptographicHashAlgorithm, so a digest can be computed while data is being transferred.
public sealed class HashingStream : Stream, IAsyncDisposable, IDisposable
- Inheritance
-
HashingStream
- Implements
- Inherited Members
- Extension Methods
Examples
// Compute a CRC-32 over a payload while streaming it to its destination - a single pass over the bytes.
using var source = File.OpenRead("payload.bin");
using var destination = File.Create("payload.copy");
using var hashing = new HashingStream(source, new Crc32());
hashing.CopyTo(destination); // every byte read from the source is fed to the CRC-32
byte[] checksum = hashing.GetCurrentHash();
Remarks
The stream is direction-agnostic: CanRead and CanWrite delegate to the inner stream, and bytes are appended to the algorithm whichever way they flow. Reads append only the bytes actually returned by the inner stream; writes append after the inner stream has accepted the bytes.
Seeking is not supported (CanSeek is always false): repositioning would let bytes bypass or re-enter the digest, silently corrupting it.
GetCurrentHash() reports the digest of the bytes transferred so far without finalizing the ongoing computation; GetHashAndReset() additionally resets the algorithm. The algorithm instance is supplied by the caller, is not disposed by this stream, and - like all NonCryptographicHashAlgorithm instances - is not thread-safe, so concurrent reads and writes through the same HashingStream are not supported.
Constructors
HashingStream(Stream, NonCryptographicHashAlgorithm, bool)
Initializes a new instance of the HashingStream class over the specified inner stream and hash algorithm.
public HashingStream(Stream innerStream, NonCryptographicHashAlgorithm algorithm, bool leaveOpen = false)
Parameters
innerStreamStreamThe stream to transfer bytes to or from. Must not be null.
algorithmNonCryptographicHashAlgorithmThe algorithm that accumulates the transferred bytes. Must not be null.
leaveOpenbooltrue to leave
innerStreamopen after this stream is disposed; otherwise, false.
Exceptions
- ArgumentNullException
innerStreamoralgorithmis null.
Properties
Algorithm
Gets the algorithm that accumulates the bytes transferred through this stream.
public NonCryptographicHashAlgorithm Algorithm { get; }
Property Value
- NonCryptographicHashAlgorithm
The NonCryptographicHashAlgorithm supplied to the constructor.
CanRead
Gets a value indicating whether the stream supports reading.
public override bool CanRead { get; }
Property Value
CanSeek
Gets a value indicating whether the stream supports seeking.
public override bool CanSeek { get; }
Property Value
CanWrite
Gets a value indicating whether the stream supports writing.
public override bool CanWrite { get; }
Property Value
Length
Gets the length of the stream. Not supported.
public override long Length { get; }
Property Value
- long
This property always throws.
Exceptions
- NotSupportedException
Always thrown; the stream does not support seeking.
Position
Gets or sets the position within the stream. Not supported.
public override long Position { get; set; }
Property Value
- long
This property always throws.
Exceptions
- NotSupportedException
Always thrown; the stream does not support seeking.
Methods
Dispose(bool)
Releases the stream, disposing the inner stream unless leaveOpen was specified. The algorithm is never
disposed.
protected override void Dispose(bool disposing)
Parameters
DisposeAsync()
Asynchronously releases the stream, disposing the inner stream unless leaveOpen was specified. The
algorithm is never disposed.
public override ValueTask DisposeAsync()
Returns
- ValueTask
A task representing the asynchronous dispose.
Flush()
Flushes the inner stream.
public override void Flush()
Exceptions
- ObjectDisposedException
The stream has been disposed.
FlushAsync(CancellationToken)
Asynchronously flushes the inner stream.
public override Task FlushAsync(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenA token used to cancel the operation.
Returns
- Task
A task representing the asynchronous flush.
Exceptions
- ObjectDisposedException
The stream has been disposed.
GetCurrentHash()
Returns the digest of the bytes transferred so far without resetting the ongoing computation.
public byte[] GetCurrentHash()
Returns
- byte[]
The current digest, sized per the algorithm's hash length.
Exceptions
- ObjectDisposedException
The stream has been disposed.
GetHashAndReset()
Returns the digest of the bytes transferred so far and resets the algorithm to its initial state.
public byte[] GetHashAndReset()
Returns
- byte[]
The digest accumulated since construction or the previous reset.
Examples
using var hashing = new HashingStream(connection, new Crc32(), leaveOpen: true);
foreach (var frame in frames)
{
hashing.Write(frame);
byte[] frameDigest = hashing.GetHashAndReset(); // digest of this frame only
Send(frameDigest);
}
Remarks
Resetting between segments lets a single HashingStream produce an independent digest per framed message over one connection, without allocating a new stream for each frame.
Exceptions
- ObjectDisposedException
The stream has been disposed.
Read(byte[], int, int)
Reads bytes from the inner stream into the buffer, appending the bytes actually read to the digest.
public override int Read(byte[] buffer, int offset, int count)
Parameters
bufferbyte[]The destination buffer. Must not be null.
offsetintThe zero-based offset in
bufferat which to begin storing data.countintThe maximum number of bytes to read.
Returns
- int
The number of bytes read, or
0at end of stream.
Exceptions
- ArgumentNullException
bufferis null.- ArgumentOutOfRangeException
offsetorcountis negative.- ArgumentException
offset+countexceeds the buffer length.- ObjectDisposedException
The stream has been disposed.
Read(Span<byte>)
Reads bytes from the inner stream into the span, appending the bytes actually read to the digest.
public override int Read(Span<byte> buffer)
Parameters
Returns
- int
The number of bytes read, or
0at end of stream.
Exceptions
- ObjectDisposedException
The stream has been disposed.
ReadAsync(byte[], int, int, CancellationToken)
Asynchronously reads bytes from the inner stream into the buffer, appending the bytes actually read to the digest.
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
Parameters
bufferbyte[]The destination buffer. Must not be null.
offsetintThe zero-based offset in
bufferat which to begin storing data.countintThe maximum number of bytes to read.
cancellationTokenCancellationTokenA token used to cancel the operation.
Returns
Exceptions
- ArgumentNullException
bufferis null.- ArgumentOutOfRangeException
offsetorcountis negative.- ArgumentException
offset+countexceeds the buffer length.- ObjectDisposedException
The stream has been disposed.
ReadAsync(Memory<byte>, CancellationToken)
Asynchronously reads bytes from the inner stream into the memory region, appending the bytes actually read to the digest.
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
Parameters
bufferMemory<byte>The destination memory region.
cancellationTokenCancellationTokenA token used to cancel the operation.
Returns
Exceptions
- ObjectDisposedException
The stream has been disposed.
ReadByte()
Reads a single byte from the inner stream, appending it to the digest when one is available.
public override int ReadByte()
Returns
- int
The byte read, or
-1at end of stream.
Exceptions
- ObjectDisposedException
The stream has been disposed.
Seek(long, SeekOrigin)
Seeks within the stream. Not supported.
public override long Seek(long offset, SeekOrigin origin)
Parameters
offsetlongThe byte offset relative to
origin. Not used; the method always throws.originSeekOriginThe reference point for
offset. Not used; the method always throws.
Returns
- long
This method always throws.
Exceptions
- NotSupportedException
Always thrown; the stream does not support seeking.
SetLength(long)
Sets the length of the stream. Not supported.
public override void SetLength(long value)
Parameters
valuelongIgnored.
Exceptions
- NotSupportedException
Always thrown; the stream does not support seeking.
Write(byte[], int, int)
Writes bytes to the inner stream and appends them to the digest.
public override void Write(byte[] buffer, int offset, int count)
Parameters
bufferbyte[]The source buffer. Must not be null.
offsetintThe zero-based offset in
bufferat which to begin reading data.countintThe number of bytes to write.
Exceptions
- ArgumentNullException
bufferis null.- ArgumentOutOfRangeException
offsetorcountis negative.- ArgumentException
offset+countexceeds the buffer length.- ObjectDisposedException
The stream has been disposed.
Write(ReadOnlySpan<byte>)
Writes bytes to the inner stream and appends them to the digest.
public override void Write(ReadOnlySpan<byte> buffer)
Parameters
bufferReadOnlySpan<byte>The source span.
Remarks
Bytes are appended to the digest after the inner stream accepts the write, so a failed write does not contaminate the digest.
Exceptions
- ObjectDisposedException
The stream has been disposed.
WriteAsync(byte[], int, int, CancellationToken)
Asynchronously writes bytes to the inner stream and appends them to the digest.
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
Parameters
bufferbyte[]The source buffer. Must not be null.
offsetintThe zero-based offset in
bufferat which to begin reading data.countintThe number of bytes to write.
cancellationTokenCancellationTokenA token used to cancel the operation.
Returns
- Task
A task representing the asynchronous write.
Exceptions
- ArgumentNullException
bufferis null.- ArgumentOutOfRangeException
offsetorcountis negative.- ArgumentException
offset+countexceeds the buffer length.- ObjectDisposedException
The stream has been disposed.
WriteAsync(ReadOnlyMemory<byte>, CancellationToken)
Asynchronously writes bytes to the inner stream and appends them to the digest.
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
Parameters
bufferReadOnlyMemory<byte>The source memory region.
cancellationTokenCancellationTokenA token used to cancel the operation.
Returns
- ValueTask
A task representing the asynchronous write.
Exceptions
- ObjectDisposedException
The stream has been disposed.
WriteByte(byte)
Writes a single byte to the inner stream and appends it to the digest.
public override void WriteByte(byte value)
Parameters
valuebyteThe byte to write.
Exceptions
- ObjectDisposedException
The stream has been disposed.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |