2011-11-22 15 views
13

क्या कोई .NET डेटा संरचना/कक्षाओं का संयोजन है जो बाइट डेटा को बफर के अंत में जोड़ने की अनुमति देता है लेकिन सभी peeks और पढ़ते हैं शुरुआत से, बफर को छोटा करते समय मैंने पढ़ा?बाइटो स्ट्रीम में विशेषज्ञता रखने वाले फीफो/क्यूई बफर

MemoryStream कक्षा इस का हिस्सा प्रतीत होता है, लेकिन मुझे पढ़ने और लिखने के लिए अलग-अलग स्थानों को बनाए रखने की आवश्यकता है, और यह पढ़ने के बाद शुरुआत में डेटा को स्वचालित रूप से त्याग नहीं देता है।

this question के जवाब में एक उत्तर पोस्ट किया गया है जो मूल रूप से मैं करने की कोशिश कर रहा हूं, लेकिन मैं एक सामान्य प्रक्रिया की तरह, एक ही प्रक्रिया के विभिन्न घटकों में एसिंक्रोनस I/O कर सकता हूं या यहां तक ​​कि एक नेटवर्क स्ट्रीम (मुझे पहले डेटा को फ़िल्टर/संसाधित करने की आवश्यकता है)।

+1

वहाँ कुछ पढ़ने बफर अंदर आगे पीछे कूद के साथ कुछ गलत है उपयोग करने के लिए कोई जरूरत नहीं है? – Ryan

+0

केवल मैंने जो कहा और उसे पढ़ने, पढ़ने, पढ़ने आदि के नेटवर्कस्ट्रीम शैली के विपरीत ट्रैक करने के लिए – Deanna

+0

क्या आपको विभिन्न आकारों के सरणी पढ़ने और लिखने की आवश्यकता है? 'बाइट []' की कतार नहीं आपके लिए पर्याप्त होगी? – svick

उत्तर

10

मैं एक परियोजना के लिए एक बार काम पर लिखने वाले कुछ तर्कों की एक अलग प्रतिलिपि पोस्ट करूंगा। इस संस्करण का लाभ यह है कि यह buffered डेटा की एक लिंक की गई सूची के साथ काम करता है और इसलिए आपको पढ़ने के दौरान स्मृति की भारी मात्रा में कैश करना होगा और/या स्मृति को प्रतिलिपि बनाना होगा। इसके अलावा, इसका धागा सुरक्षित है और नेटवर्क स्ट्रीम की तरह व्यवहार करता है, जो है: जब कोई डेटा उपलब्ध नहीं होता है तब पढ़ते समय: डेटा उपलब्ध या टाइमआउट होने तक प्रतीक्षा करें। साथ ही, बाइट्स की एक्स मात्रा पढ़ने पर और केवल बाइट्स की मात्रा होती है, सभी बाइट पढ़ने के बाद वापस आती है। आशा है कि ये आपकी मदद करेगा!

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<ArraySegment<byte>> _pendingSegments = new LinkedList<ArraySegment<byte>>(); 
    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<byte> 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<byte>(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<byte>(copy)); 

      _dataAvailableResetEvent.Set(); 
     } 
    } 
} 
+1

अच्छा लगता है, और जिस तरह से मैं जा रहा था वही था। मैं आज रात कोशिश करूँगा। – Deanna

+0

ऐसा लगता है कि यदि आप कोई भी उपलब्ध नहीं है तो डेटा पढ़ने की कोशिश करते हैं तो यह क्रैश हो जाएगा। – svick

+0

@ एसविक - बिल्कुल सही, यह सिर्फ एक मसौदा, कोई तर्क सत्यापन आदि नहीं है। मैन्युअल रीसेट इवेंट उस एकमात्र कारण के लिए है, मैं बस पढ़ने की विधि की शुरुआत में प्रतीक्षा करना भूल गया। अब तय हेडस – Polity

1

कोड स्वीकृत उत्तर से सरल हो सकता है। एक for पाश .:

/// <summary> 
/// This class is a very fast and threadsafe FIFO buffer 
/// </summary> 
public class FastFifo 
{ 
    private List<Byte> mi_FifoData = new List<Byte>(); 

    /// <summary> 
    /// Get the count of bytes in the Fifo buffer 
    /// </summary> 
    public int Count 
    { 
     get 
     { 
      lock (mi_FifoData) 
      { 
       return mi_FifoData.Count; 
      } 
     } 
    } 

    /// <summary> 
    /// Clears the Fifo buffer 
    /// </summary> 
    public void Clear() 
    { 
     lock (mi_FifoData) 
     { 
      mi_FifoData.Clear(); 
     } 
    } 

    /// <summary> 
    /// Append data to the end of the fifo 
    /// </summary> 
    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); 
     } 
    } 

    /// <summary> 
    /// Get data from the beginning of the fifo. 
    /// returns null if s32_Count bytes are not yet available. 
    /// </summary> 
    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; 
     } 
    } 

    /// <summary> 
    /// Gets a byte without removing it from the Fifo buffer 
    /// returns -1 if the index is invalid 
    /// </summary> 
    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]; 
     } 
    } 
} 
+0

यह अनिवार्य रूप से लिंक किए गए प्रश्न जैसा ही है, जो असीमित या अवरुद्ध इच्छाओं को पूरा नहीं करता है। हालांकि धन्यवाद। – Deanna

+0

ठीक है, लेकिन वह कोड इतना सुरुचिपूर्ण नहीं है और यह धागा सुरक्षित नहीं है। आप इसे 16 लाइनों की आवश्यकता के बजाय 6 लाइनों के साथ कर सकते हैं। – Elmue

संबंधित मुद्दे