2009-02-06 13 views
17

क्या स्ट्रीमरडर को किसी भी बफरिंग से रखने का कोई तरीका है?Unbuffered StreamReader

मैं एक प्रक्रिया से आउटपुट को संभालने की कोशिश कर रहा हूं जो या तो बाइनरी या टेक्स्ट हो सकता है। आउटपुट एक HTTP प्रतिक्रिया की तरह दिखेगा, उदा।

Content-type: application/whatever 
Another-header: value 

text or binary data here 

मुझे क्या करना चाहते हैं एक StreamReader का उपयोग कर हेडर पार्स करने के लिए है, और फिर या तो की शेष सामग्री को संभालने की BaseStream या StreamReader से पढ़ें। यहां मूल रूप से मैंने जो शुरू किया है:

private static readonly Regex HttpHeader = new Regex("([^:]+): *(.*)"); 
private void HandleOutput(StreamReader reader) 
{ 
    var headers = new NameValueCollection(); 
    string line; 
    while((line = reader.ReadLine()) != null) 
    { 
    Match header = HttpHeader.Match(line); 
    if(header.Success) 
    { 
     headers.Add(header.Groups[1].Value, header.Groups[2].Value); 
    } 
    else 
    { 
     break; 
    } 
    } 
    DoStuff(reader.ReadToEnd()); 
} 

यह कचरा बाइनरी डेटा लगता है। इसलिए मैं कुछ इस तरह करने के लिए अंतिम पंक्ति बदल दिया है:

if(headers["Content-type"] != "text/html") 
{ 
    // reader.BaseStream.Position is not at the same place that reader 
    // makes it looks like it is. 
    // i.e. reader.Read() != reader.BaseStream.Read() 
    DoBinaryStuff(reader.BaseStream); 
} 
else 
{ 
    DoTextStuff(reader.ReadToEnd()); 
} 

... लेकिन StreamReader अपने इनपुट बफ़र्स, तो reader.BaseStream गलत स्थिति में है। क्या StreamReader unbuffer करने का कोई तरीका है? या क्या स्ट्रीम स्ट्रीमर स्ट्रीम स्ट्रीमर को स्ट्रीम रीडर रीसेट करने के लिए कह सकता हूं?

+0

मैट - क्या आप "स्ट्रीमर रीडर एक समय में ब्लॉक पढ़ते हैं, इसलिए पाठक। बेसस्ट्रीम गलत स्थिति में है।" – jro

+0

उम्मीद है कि यह स्पष्ट है। –

उत्तर

0

ठीक है, आप स्ट्रीम की स्थिति निर्धारित करने के लिए Stream.Seek का उपयोग कर सकते हैं। यह मुझे लगता है कि आप जिस समस्या का सामना कर रहे हैं, वह यह है कि StreamReader बाइट्स के बजाय वर्ण पढ़ रहा है (जो, एन्कोडिंग के आधार पर, 1 बाइट प्रति चरित्र से अलग हो सकता है)। से MSDN Library:

StreamReader एक विशेष एन्कोडिंग में चरित्र इनपुट के लिए बनाया गया है, जबकि स्ट्रीम वर्ग बाइट इनपुट और आउटपुट के लिए बनाया गया है।

जब आप पाठक को कॉल करते हैं। ReadToEnd(), यह डेटा को किसी भी एन्कोडिंग के आधार पर वर्ण स्ट्रिंग के रूप में पढ़ता है। Stream.Read विधि का उपयोग करके आपको बेहतर भाग्य हो सकता है। StreamReader के साथ अपने स्ट्रिंग डेटा में पढ़ें और उसके बाद बाइनरी डेटा को बाइट [] में खींचें जब आपने हेडर में पढ़ा है जो आपको आने वाले बाइनरी डेटा की सूचना देता है।

+0

ठीक है, आप नेटवर्कस्ट्रीम के भीतर नहीं खोज सकते हैं। – nitrocaster

8

यह उत्तर देर से और संभवतः आपके लिए प्रासंगिक नहीं है लेकिन यह किसी और के लिए काम में आ सकता है जो इस समस्या से गुज़रता है।

मेरे समस्या शामिल PPM files, जिनमें से एक ऐसी ही प्रारूप है: शुरुआत में

  • फ़ाइल
  • समस्या मैं था में भाग के बाकी के लिए बाइनरी बाइट्स

    • ASCII पाठ कि StreamReader कक्षा सामान को बफर किए बिना एक बार एक बाइट सामान पढ़ने में असमर्थ है। इससे कुछ मामलों में अप्रत्याशित परिणाम हुए, क्योंकि Read() विधि एक एकल वर्ण पढ़ता है, एक एकल बाइट नहीं।

      मेरा समाधान एक स्ट्रीम के चारों ओर एक रैपर लिखना था जो एक समय में बाइट्स को पढ़ता था। रैपर में 2 महत्वपूर्ण विधियां हैं, ReadLine() और Read()

      ये 2 विधियां मुझे स्ट्रीम की एएससीआईआईआई लाइनों को पढ़ने, अनबफर किए जाने की अनुमति देती हैं, और फिर शेष स्ट्रीम के लिए एक बार में एक बाइट पढ़ती हैं। आपको अपनी जरूरतों के अनुरूप कुछ समायोजन करने की आवश्यकता हो सकती है।

      class UnbufferedStreamReader: TextReader 
      { 
          Stream s; 
      
          public UnbufferedStreamReader(string path) 
          { 
           s = new FileStream(path, FileMode.Open); 
          } 
      
          public UnbufferedStreamReader(Stream stream) 
          { 
           s = stream; 
          } 
      
          // This method assumes lines end with a line feed. 
          // You may need to modify this method if your stream 
          // follows the Windows convention of \r\n or some other 
          // convention that isn't just \n 
          public override string ReadLine() 
          { 
           List<byte> bytes = new List<byte>(); 
           int current; 
           while ((current = Read()) != -1 && current != (int)'\n') 
           { 
            byte b = (byte)current; 
            bytes.Add(b); 
           } 
           return Encoding.ASCII.GetString(bytes.ToArray()); 
          } 
      
          // Read works differently than the `Read()` method of a 
          // TextReader. It reads the next BYTE rather than the next character 
          public override int Read() 
          { 
           return s.ReadByte(); 
          } 
      
          public override void Close() 
          { 
           s.Close(); 
          } 
          protected override void Dispose(bool disposing) 
          { 
           s.Dispose(); 
          } 
      
          public override int Peek() 
          { 
           throw new NotImplementedException(); 
          } 
      
          public override int Read(char[] buffer, int index, int count) 
          { 
           throw new NotImplementedException(); 
          } 
      
          public override int ReadBlock(char[] buffer, int index, int count) 
          { 
           throw new NotImplementedException(); 
          }  
      
          public override string ReadToEnd() 
          { 
           throw new NotImplementedException(); 
          } 
      } 
      
    +0

    अपने समाधान को बेहतर बनाने के लिए आपको बेस क्लास TextReader की परिभाषा को पूरा करने के लिए बाइट्स सूची खाली होने पर शून्य को वापस करने की आवश्यकता है। वर्तमान में आप एक खाली स्ट्रिंग लौट रहे हैं। – Doomjunky

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