如何在不截断的情况下设置流中的长度

  • 本文关键字:设置 情况下 c# stream
  • 更新时间 :
  • 英文 :


它指出,通过使用Stream.SetLength,流被截断。源

我需要在不进行截断的情况下设置流的长度。

有内置的可能性吗?

更新:我需要读取一个文件的子集。文件格式:大小+数据(字符串格式)。

Im使用StreamReader

更新2:我对使用StreamReader类中的ReadLine也很感兴趣。

我需要读取文件的子集

好的,所以你实际上不想设置长度。你想读一个特定的长度。

为自己编写一个Stream子类,它只读取一定数量的字节。然后,您可以用该类包装文件流,StreamReader就可以工作了。

或者,如果缓冲数据是可以的,您可以这样做:

var limitedStream = new MemoryStream(new BinaryReader(myStream).ReadBytes(length));

我同意@usr关于创建子类Stream包装器的回答。这里有一个示例实现,它将所有调用转发到"内部"流,但在读取过程中或当被要求提供Length时会涉及到它。此实现不支持任何涉及编写的内容。

我还没有完全测试这个实现,我欢迎来自社区的编辑:

sealed class StreamReadLimitLengthWrapper : Stream
{
    readonly Stream m_innerStream;
    readonly long m_endPosition;
    public StreamReadLimitLengthWrapper(Stream innerStream, int size)
    {
        if (innerStream == null) throw new ArgumentNullException("innerStream");
        if (size < 0) throw new ArgumentOutOfRangeException("size");
        m_innerStream = innerStream;
        m_endPosition = m_innerStream.Position + size;
    }
    public override bool CanRead
    {
        get { return m_innerStream.CanRead; }
    }
    public override bool CanSeek
    {
        get { return m_innerStream.CanSeek; }
    }
    public override bool CanWrite
    {
        get { return false; }
    }
    public override void Flush()
    {
        m_innerStream.Flush();
    }
    public override long Length
    {
        get { return m_endPosition; }
    }
    public override long Position
    {
        get
        {
            return m_innerStream.Position;
        }
        set
        {
            m_innerStream.Position = value;
        }
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        count = GetAllowedCount(count);
        return m_innerStream.Read(buffer, offset, count);
    }
    public override long Seek(long offset, SeekOrigin origin)
    {
        return m_innerStream.Seek(offset, origin);
    }
    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }
    public override bool CanTimeout { get { return m_innerStream.CanTimeout; } }
    public override int ReadTimeout
    {
        get
        {
            return m_innerStream.ReadTimeout;
        }
        set
        {
            m_innerStream.ReadTimeout = value;
        }
    }
    public override int WriteTimeout
    {
        get
        {
            return m_innerStream.ReadTimeout;
        }
        set
        {
            m_innerStream.ReadTimeout = value;
        }
    }
    public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
    {
        count = GetAllowedCount(count);
        return m_innerStream.BeginRead(buffer, offset, count, callback, state);
    }
    public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
    {
        throw new NotSupportedException();
    }
    public override void Close()
    {
        // Since this wrapper does not own the underlying stream, we do not want it to close the underlying stream
    }
    public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
    {
        return m_innerStream.CopyToAsync(destination, bufferSize, cancellationToken);
    }
    public override int EndRead(IAsyncResult asyncResult)
    {
        return m_innerStream.EndRead(asyncResult);
    }
    public override Task FlushAsync(CancellationToken cancellationToken)
    {
        return m_innerStream.FlushAsync(cancellationToken);
    }
    public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        count = GetAllowedCount(count);
        return m_innerStream.ReadAsync(buffer, offset, count, cancellationToken);
    }
    public override int ReadByte()
    {
        int count = GetAllowedCount(1);
        if (count == 0)
            return -1;
        return m_innerStream.ReadByte();
    }
    public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        throw new NotSupportedException();
    }
    public override void WriteByte(byte value)
    {
        throw new NotSupportedException();
    }
    private int GetAllowedCount(int count)
    {
        long pos = m_innerStream.Position;
        long maxCount = m_endPosition - pos;
        if (count > maxCount)
            count = (int)maxCount;
        return count;
    }
}

您在这里问错了问题。流的Length是可从流中读取的已知字节量。设置流的长度会更改源,以确保它使用指定的长度。


既然你只是想限制你从流中读取的内容,那么你只需要读取你需要的内容并关闭它。你不需要做任何其他事情。

由于您似乎正在尝试读取文本文件,请按照正常的文件读取模式,并提出适当的停止条件。您甚至不需要流,File类提供了读取文件行的简单方法。

foreach (var line in File.ReadLines(path))
{
    // do something with line...
    if (line == "end of interesting section")
        break;
}

相关内容

  • 没有找到相关文章

最新更新