在 .NET 中,自然无法保证知道
Stream
的长度,因为这可能来自某些外部源(例如网络),尚未交付全部内容,甚至可能没有计算还没有。
相反,我正在寻找的是如何在阅读整个内容后知道长度
Stream
?
我可以通过在
Stream
周围做一个中间层包装器来自己解决这个问题(如果你想计算内容的哈希值,你可以用 CryptoStream
来做)但是这很麻烦,所以我会想避免这种情况(我猜我忽略了一种简单的方法)。
请不要发布任何涉及将
Stream
的内容存储在内存中的解决方案(例如,将其复制到 MemoryStream
或字节数组)。
如果您拥有流式阅读代码,最简单的方法是在阅读时保持计数:
ulong totalBytes = 0;
do
{
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
totalBytes += (ulong)bytesRead;
// do something with buffer
} while (bytesRead > 0);
您可以在完全阅读流后进一步使用
totalBytes
如果不自己读取流,而是传递给其他代码,这是不可行的
对于选择的流,您可以在阅读后(但在处理之前)使用
Postion
属性。他们会记下他们在哪里。这不适用于不可搜索的流,也不适用于读者处理的流。
这让您可以实现自己的包装器,在
Read
中保持计数(最终由 BeginRead
和 ReadAsync
调用):
public sealed class ByteCountingStream : Stream
{
private readonly Stream _adaptee;
private readonly bool _ownsStream;
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => throw new NotSupportedException();
public override long Position {
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public ulong BytesRead { get; private set; }
public ByteCountingStream(Stream adaptee, bool ownsStream = true)
{
if (!adaptee.CanRead)
{
throw new NotSupportedException();
}
_adaptee = adaptee;
_ownsStream = ownsStream;
}
public override int Read(byte[] buffer, int offset, int count)
{
int bytesRead = _adaptee.Read(buffer, 0, buffer.Length);
BytesRead += (ulong)bytesRead;
return bytesRead;
}
protected override void Dispose(bool disposing)
{
if (_ownsStream)
{
_adaptee.Dispose();
}
}
public override void Flush() => throw new NotSupportedException();
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
}
然后就可以使用了:
await using var countingStream = new ByteCountingStream(underlyingStream);
await SomeStreamReadingMethod(countingStream);
var uploadedFileSize = countingStream.BytesRead;
然后就可以使用
uploadedFileSize
了。现在如果你想支持寻求,你有另一个问题......