阅读时/阅读后如何在 .NET 中测量流的长度

问题描述 投票:0回答:1

在 .NET 中,自然无法保证知道

Stream
的长度,因为这可能来自某些外部源(例如网络),尚未交付全部内容,甚至可能没有计算还没有。

相反,我正在寻找的是如何在阅读整个内容后知道长度

Stream

我可以通过在

Stream
周围做一个中间层包装器来自己解决这个问题(如果你想计算内容的哈希值,你可以用
CryptoStream
来做)但是这很麻烦,所以我会想避免这种情况(我猜我忽略了一种简单的方法)。

请不要发布任何涉及将

Stream
的内容存储在内存中的解决方案(例如,将其复制到
MemoryStream
或字节数组)。

c# .net stream
1个回答
0
投票

如果您拥有流式阅读代码,最简单的方法是在阅读时保持计数:

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
了。现在如果你想支持寻求,你有另一个问题......

© www.soinside.com 2019 - 2024. All rights reserved.