FIFO /队列缓冲区专门用于字节流

是否有任何.NET数据结构/类组合允许将字节数据附加到缓冲区的末尾,但所有的查找和读取都是从一开始,在我读取时缩短缓冲区?

MemoryStream类似乎也是其中的一部分,但是我需要为读取和写入维护单独的位置,并且它在读取后不会自动丢弃数据。

答案已经回复了这个问题 ,这基本上就是我要做的事情,但我更喜欢我可以在同一个过程的不同组件中进行异步I / O,就像普通管道甚至是网络流(我需要先过滤/处理数据)。

我将发布一份我曾为工作项目写过的逻辑的剥离副本。 这个版本的优点是它可以使用缓冲数据的链接列表,因此您无需在读取时缓存大量内存和/或复制内存。 此外,它的线程安全且行为类似于网络流,即:当没有可用数据时读取:等待直到有可用数据或超时。 此外,当读取x个字节数并且只有y个字节时,在读取所有字节后返回。 我希望这有帮助!

  public class SlidingStream : Stream { #region Other stream member implementations ... #endregion Other stream member implementations public SlidingStream() { ReadTimeout = -1; } private readonly object _writeSyncRoot = new object(); private readonly object _readSyncRoot = new object(); private readonly LinkedList> _pendingSegments = new LinkedList>(); private readonly ManualResetEventSlim _dataAvailableResetEvent = new ManualResetEventSlim(); public int ReadTimeout { get; set; } public override int Read(byte[] buffer, int offset, int count) { if (_dataAvailableResetEvent.Wait(ReadTimeout)) throw new TimeoutException("No data available"); lock (_readSyncRoot) { int currentCount = 0; int currentOffset = 0; while (currentCount != count) { ArraySegment segment = _pendingSegments.First.Value; _pendingSegments.RemoveFirst(); int index = segment.Offset; for (; index < segment.Count; index++) { if (currentOffset < offset) { currentOffset++; } else { buffer[currentCount] = segment.Array[index]; currentCount++; } } if (currentCount == count) { if (index < segment.Offset + segment.Count) { _pendingSegments.AddFirst(new ArraySegment(segment.Array, index, segment.Offset + segment.Count - index)); } } if (_pendingSegments.Count == 0) { _dataAvailableResetEvent.Reset(); return currentCount; } } return currentCount; } } public override void Write(byte[] buffer, int offset, int count) { lock (_writeSyncRoot) { byte[] copy = new byte[count]; Array.Copy(buffer, offset, copy, 0, count); _pendingSegments.AddLast(new ArraySegment(copy)); _dataAvailableResetEvent.Set(); } } } 

代码可以比接受的答案更简单。 不需要使用for循环:

 ///  /// This class is a very fast and threadsafe FIFO buffer ///  public class FastFifo { private List mi_FifoData = new List(); ///  /// Get the count of bytes in the Fifo buffer ///  public int Count { get { lock (mi_FifoData) { return mi_FifoData.Count; } } } ///  /// Clears the Fifo buffer ///  public void Clear() { lock (mi_FifoData) { mi_FifoData.Clear(); } } ///  /// Append data to the end of the fifo ///  public void Push(Byte[] u8_Data) { lock (mi_FifoData) { // Internally the .NET framework uses Array.Copy() which is extremely fast mi_FifoData.AddRange(u8_Data); } } ///  /// Get data from the beginning of the fifo. /// returns null if s32_Count bytes are not yet available. ///  public Byte[] Pop(int s32_Count) { lock (mi_FifoData) { if (mi_FifoData.Count < s32_Count) return null; // Internally the .NET framework uses Array.Copy() which is extremely fast Byte[] u8_PopData = new Byte[s32_Count]; mi_FifoData.CopyTo(0, u8_PopData, 0, s32_Count); mi_FifoData.RemoveRange(0, s32_Count); return u8_PopData; } } ///  /// Gets a byte without removing it from the Fifo buffer /// returns -1 if the index is invalid ///  public int PeekAt(int s32_Index) { lock (mi_FifoData) { if (s32_Index < 0 || s32_Index >= mi_FifoData.Count) return -1; return mi_FifoData[s32_Index]; } } }