【问题标题】:How to set length in stream without truncated?如何在流中设置长度而不被截断?
【发布时间】:2015-10-26 20:18:38
【问题描述】:

它声明通过使用Stream.SetLength 流被截断source

我需要设置流的长度没有截断。

任何内置的可能性?

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

我正在使用StreamReader

更新2: 我也非常喜欢使用StreamReader 类中的ReadLine

【问题讨论】:

  • 那你预计会发生什么?
  • 你错过了句子的关键部分,“如果指定的值小于流的当前长度,则流被截断。”如果将长度设置为小于当前长度,它还应该做什么?
  • 您要解决的总体问题是什么?
  • 不截断流的唯一方法是让它更长,那么额外的数据从哪里来?如果你把它再缩短一点,那么数据去哪儿了?有点像想从膝盖处剪掉你的腿,但你不想变短......
  • 所以你只是想读取文件的一部分?您可以在没有SetLength 的情况下执行此操作。

标签: c# stream


【解决方案1】:

我需要读取文件的子集

好的,所以你不想实际设置长度。您想阅读特定的长度。

给自己写一个Stream 子类,它只读取一定数量的字节。然后,您可以使用该类包装文件流,StreamReader 将正常工作。

或者,如果缓冲数据没问题,你可以这样做:

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

【讨论】:

    【解决方案2】:

    我同意@usr 关于创建子类 Stream 包装器的回答。这是一个示例实现,它将所有调用转发到“内部”流,但在读取期间或在询问长度时涉及。此实现不支持任何涉及写入的内容。

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

    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;
        }
    }
    

    【讨论】:

      【解决方案3】:

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


      由于您只想限制从流中读取的数量,因此只需根据需要读取并关闭它即可。你不需要做任何其他事情。

      由于您似乎正在尝试读取文本文件,因此只需使用正常的文件读取模式并提出适当的停止条件即可。您甚至不需要流,File 类提供了读取文件行的​​简单方法。

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

      【讨论】:

        猜你喜欢
        • 2018-01-14
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 2019-09-10
        • 2019-12-17
        • 2012-03-19
        • 2012-03-25
        相关资源
        最近更新 更多