मैं एक स्ट्रिंग से एक स्ट्रीम कैसे उत्पन्न कर सकता हूं?


759

मुझे एक विधि के लिए एक इकाई परीक्षण लिखना होगा जो एक धारा लेता है जो एक पाठ फ़ाइल से आता है। मैं ऐसा कुछ करना चाहूंगा:

Stream s = GenerateStreamFromString("a,b \n c,d");

स्मृति की बचत समाधान के लिए, देखें StringReaderStreamमें stackoverflow.com/a/55170901/254109
xmedeko

जवाबों:


956
public static Stream GenerateStreamFromString(string s)
{
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream);
    writer.Write(s);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

उपयोग करना न भूलें:

using (var stream = GenerateStreamFromString("a,b \n c,d"))
{
    // ... Do stuff to stream
}

बारे में StreamWriterनिपटारा नहीं किया जा रहा। StreamWriterबस बेस स्ट्रीम के आसपास एक आवरण है, और किसी भी संसाधन का उपयोग नहीं करता है जिसे निपटाने की आवश्यकता है। Disposeविधि बंद हो जाएगा अंतर्निहित Streamहै कि StreamWriterकरने के लिए लिख रहे हैं। इस मामले में कि MemoryStreamहम लौटना चाहते हैं।

.NET 4.5 में अब एक अधिभार है StreamWriterजो लेखक के निपटारे के बाद अंतर्निहित स्ट्रीम को खुला रखता है, लेकिन यह कोड यही काम करता है और .NET के अन्य संस्करणों के साथ भी काम करता है।

देखें कि क्या कोई बेस स्ट्रीमर को बंद किए बिना किसी स्ट्रीमराइटर को बंद करने का कोई तरीका है?


134
इंगित करने के लिए एक महत्वपूर्ण बिंदु अवधारणा यह है कि एक धारा बाइट्स से बना है, जबकि एक स्ट्रिंग वर्णों से बना है। यह समझना महत्वपूर्ण है कि एक चरित्र को एक या एक से अधिक बाइट्स में बदलना (या इस मामले में एक स्ट्रीम के रूप में) हमेशा एक विशेष एन्कोडिंग का उपयोग करता है (या मानता है)। यह उत्तर, कुछ मामलों में सही होने पर, डिफ़ॉल्ट एन्कोडिंग का उपयोग करता है, और सामान्य रूप से उपयुक्त नहीं हो सकता है। स्पष्ट रूप से StreamWriter कंस्ट्रक्टर को एन्कोडिंग पास करने से यह अधिक स्पष्ट हो जाएगा कि लेखक को एन्कोडिंग के निहितार्थों पर विचार करने की आवश्यकता है।
drwatsoncode

6
आप कहते हैं "स्ट्रीम का उपयोग करने के लिए" का उपयोग करने के लिए मत भूलना, लेकिन अपने GenerateStreamFromStringतरीके में आप StreamWriter के साथ प्रयोग नहीं कर रहे हैं। क्या इसका कोई कारण है?
बेन

12
@ हाँ। यदि आप StreamWriter का निपटान करते हैं तो अंतर्निहित स्ट्रीम भी बंद हो जाएगी। हम ऐसा नहीं चाहते हैं। राइटर डिस्पोजेबल होने का एकमात्र कारण स्ट्रीम को साफ करना है, इसलिए इसे अनदेखा करना सुरक्षित है।
कैमरन मैकफारलैंड

2
यह भी ध्यान दिया जाना चाहिए, कि पूरे स्ट्रिंग को एक मेमोरी में कॉपी किया जाता है जो बड़े स्ट्रिंग्स के लिए महत्वपूर्ण हो सकता है क्योंकि अब हमारे पास मेमोरी में एक अतिरिक्त कॉपी है।
UGEEN

1
@ वास्तव में नहीं। StreamWriterशायद वही कर रहे हैं जो आपने वैसे भी आंतरिक रूप से कहा था। लाभ एन्कैप्सुलेशन और सरल कोड है, लेकिन इनकोडिंग की तरह अमूर्त चीजों की कीमत पर। यह इस बात पर निर्भर करता है कि आप क्या हासिल करना चाहते हैं।
कैमरून मैकफारलैंड

724

एक और समाधान:

public static MemoryStream GenerateStreamFromString(string value)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}

31
बस अगर कोई इसे XML स्ट्रिंग डिसेरिएलाइजेशन के साथ उपयोग करता है, तो मुझे इसके लिए UTF8 को एक ध्वज के बिना काम करने के लिए यूनिकोड पर स्विच करना होगा। महान पद!!!
गैसपा 79

2
मुझे यह पसंद है (स्वीकृत विधि के रूप में उपयोग के लिए रयूस के ट्विक और तुच्छ अतिरिक्त चीनी के साथ) स्वीकार किए गए उत्तर से बेहतर है; अधिक लचीली, कम LOC और कम ऑब्जेक्ट शामिल हैं (
स्ट्रीमड्राइटर के

2
new MemoryStream(Encoding.UTF8.GetBytes("\ufeff" + (value ?? ""))अगर आपको BOM स्ट्रीम की शुरुआत में शामिल होना चाहिए
robert4

5
यह बहुत कॉम्पैक्ट सिंटैक्स है, लेकिन यह बाइट के आवंटन के बहुत सारे कारण है [] इसलिए उच्च प्रदर्शन कोड में सावधान रहें।
michael.aird

1
इस समाधान ने धारा को आसानी से बनाने का अवसर छोड़ दिया। new MemoryStream( value, false )। यदि आप इसे स्ट्रीम लेखक के साथ लिखना चाहते हैं तो आप एक स्ट्रीम आसानी से नहीं बना सकते।
कोडकंडिस

106

इसे स्टैटिक स्ट्रिंग यूटिलिटी क्लास में जोड़ें:

public static Stream ToStream(this string str)
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(str);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

यह एक एक्सटेंशन फ़ंक्शन जोड़ता है ताकि आप बस:

using (var stringStream = "My string".ToStream())
{
    // use stringStream
}

5
मुझे पता चला कि जब गारबेज कलेक्टर सफाई करता है तो लौटी हुई धारा बंद हो जाती है (अर्ध-यादृच्छिक अपवादों को पैदा करते हुए) StreamWriter। फ़िक्स को एक अलग कंस्ट्रक्टर का उपयोग करना था - एक जिसने मुझे लीवऑन को निर्दिष्ट करने की अनुमति दी ।
बेवन


24

पहले बाइट्स के एक सरणी में अपने स्ट्रिंग को चालू करने के लिए MemoryStreamकॉल Encoding.GetBytesकरते हुए, क्लास का उपयोग करें ।

क्या आपको बाद TextReaderमें धारा पर कोई ज़रूरत है ? यदि हां, तो आप StringReaderसीधे आपूर्ति कर सकते हैं , MemoryStreamऔर Encodingकदमों को दरकिनार कर सकते हैं ।


22

मैंने इस तरह के उत्तर का मिश्रण इस्तेमाल किया:

public static Stream ToStream(this string str, Encoding enc = null)
{
    enc = enc ?? Encoding.UTF8;
    return new MemoryStream(enc.GetBytes(str ?? ""));
}

और फिर मैं इसे इस तरह से उपयोग करता हूं:

String someStr="This is a Test";
Encoding enc = getEncodingFromSomeWhere();
using (Stream stream = someStr.ToStream(enc))
{
    // Do something with the stream....
}

थॉमस, वोट डाउन क्यों? एन्क = एनक ?? Encoding.UTF8 मुझे विशिष्ट एन्कोडिंग, या UTF8 के एक डिफ़ॉल्ट के साथ विशेष रूप से स्ट्रीम पूछने की अनुमति देता है, और क्योंकि .net (जहाँ तक मैं इसका उपयोग करता हूँ .net 4.0) आप फ़ंक्शन में एक डिफ़ॉल्ट मान स्ट्रिंग के अलावा एक संदर्भ प्रकार नहीं दे सकते। हस्ताक्षर यह लाइन आवश्यक है, क्या इसका मतलब है?
रोबोकाइड

यह उल्लेख करते हुए कि आपको इसे एक अलग वर्ग (गैर जेनेरिक स्टैटिक क्लास?) में रखने की आवश्यकता है, यह भी सहायक है और नीचे के वोटों को कम करता है।
अली

13

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

public static class StringExtensions {

    public static Stream ToStream(this string s) {
        return s.ToStream(Encoding.UTF8);
    }

    public static Stream ToStream(this string s, Encoding encoding) {
        return new MemoryStream(encoding.GetBytes(s ?? ""));
    }
}

1
मैं पहले तरीके को लागू करना पसंद करूंगा return ToStream(s, Encoding.UTF8);। वर्तमान कार्यान्वयन में ( return s.ToStream(Encoding.UTF8);, डेवलपर को कोड को समझने के लिए कठिन सोचने के लिए मजबूर किया जाता है और ऐसा लगता है कि मामला s == nullNullReferenceException
अनहैंड

10

हेयर यू गो:

private Stream GenerateStreamFromString(String p)
{
    Byte[] bytes = UTF8Encoding.GetBytes(p);
    MemoryStream strm = new MemoryStream();
    strm.Write(bytes, 0, bytes.Length);
    return strm;
}

1
लिखने के बाद स्थिति को रीसेट करने की आवश्यकता है। जोएलनेट के जवाब में, निर्माता का उपयोग करने के लिए बेहतर है।
जिम बेल्टर

10

के लिए विस्तार विधियों का आधुनिकीकरण और थोड़ा संशोधित संस्करण ToStream:

public static Stream ToStream(this string value) => ToStream(value, Encoding.UTF8);

public static Stream ToStream(this string value, Encoding encoding) 
                          => new MemoryStream(encoding.GetBytes(value ?? string.Empty));

संशोधन के रूप में @ पलाश की टिप्पणी @ पलक की टिप्पणी में उत्तर दिया गया।



3

यदि आपको @ShaunBowe के समाधान के लिए मेरे द्वारा दिए गए एन्कोडिंग को बदलने की आवश्यकता है । लेकिन यहां हर उत्तर कम से कम एक बार पूरे स्ट्रिंग को मेमोरी में कॉपी करता है। ToCharArray+ BlockCopyकॉम्बो के साथ उत्तर दो बार करते हैं।

यदि यह मायने रखता है Streamतो कच्चे UTF-16 स्ट्रिंग के लिए एक सरल आवरण है। यदि इसके लिए StreamReaderचयन के साथ प्रयोग किया जाता Encoding.Unicodeहै:

public class StringStream : Stream
{
    private readonly string str;

    public override bool CanRead => true;
    public override bool CanSeek => true;
    public override bool CanWrite => false;
    public override long Length => str.Length * 2;
    public override long Position { get; set; } // TODO: bounds check

    public StringStream(string s) => str = s ?? throw new ArgumentNullException(nameof(s));

    public override long Seek(long offset, SeekOrigin origin)
    {
        switch (origin)
        {
            case SeekOrigin.Begin:
                Position = offset;
                break;
            case SeekOrigin.Current:
                Position += offset;
                break;
            case SeekOrigin.End:
                Position = Length - offset;
                break;
        }

        return Position;
    }

    private byte this[int i] => (i & 1) == 0 ? (byte)(str[i / 2] & 0xFF) : (byte)(str[i / 2] >> 8);

    public override int Read(byte[] buffer, int offset, int count)
    {
        // TODO: bounds check
        var len = Math.Min(count, Length - Position);
        for (int i = 0; i < len; i++)
            buffer[offset++] = this[(int)(Position++)];
        return (int)len;
    }

    public override int ReadByte() => Position >= Length ? -1 : this[(int)Position++];
    public override void Flush() { }
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
    public override string ToString() => str; // ;)     
}

और यहाँ आवश्यक बाउंड चेक के साथ एक और अधिक पूर्ण समाधान है ( MemoryStreamताकि यह भी है ToArrayऔर WriteToसाथ ही तरीके)।


-2

स्ट्रिंग एक्सटेंशन का एक अच्छा संयोजन:

public static byte[] GetBytes(this string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

public static Stream ToStream(this string str)
{
    Stream StringStream = new MemoryStream();
    StringStream.Read(str.GetBytes(), 0, str.Length);
    return StringStream;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.