स्ट्रिंग और वापस करने के लिए स्ट्रीम परिवर्तित ... क्या हम याद कर रहे हैं?


162

मैं वस्तुओं को स्ट्रिंग में क्रमबद्ध करना चाहता हूं, और वापस।

हम किसी ऑब्जेक्ट को स्ट्रीम और बैक में, सफलतापूर्वक चालू करने के लिए प्रोटोबॉफ-नेट का उपयोग करते हैं।

हालांकि, स्ट्रीम टू स्ट्रिंग और बैक ... इतना सफल नहीं है। के माध्यम से जाने के बाद StreamToStringऔर StringToStream, नए Streamप्रोटोबुफ़-नेट द्वारा deserialized नहीं है; यह एक Arithmetic Operation resulted in an Overflowअपवाद को जन्म देता है। यदि हम मूल धारा का वर्णन करते हैं, तो यह काम करता है।

हमारे तरीके:

public static string StreamToString(Stream stream)
{
    stream.Position = 0;
    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
    {
        return reader.ReadToEnd();
    }
}

public static Stream StringToStream(string src)
{
    byte[] byteArray = Encoding.UTF8.GetBytes(src);
    return new MemoryStream(byteArray);
}

इन दोनों का उपयोग करके हमारा उदाहरण कोड:

MemoryStream stream = new MemoryStream();
Serializer.Serialize<SuperExample>(stream, test);
stream.Position = 0;
string strout = StreamToString(stream);
MemoryStream result = (MemoryStream)StringToStream(strout);
var other = Serializer.Deserialize<SuperExample>(result);

1
क्या स्ट्रीम मेमोरीस्ट्रीम नहीं होनी चाहिए?
एहसान

जवाबों:


60

यह इतना सामान्य है लेकिन बहुत गलत है। प्रोटोबॉफ़ डेटा स्ट्रिंग डेटा नहीं है। यह निश्चित रूप से ASCII नहीं है। आप पीछे की ओर एन्कोडिंग का उपयोग कर रहे हैं । एक पाठ एन्कोडिंग स्थानान्तरण:

  • एक मनमाना स्ट्रिंग स्वरूपित बाइट्स के लिए
  • मूल स्ट्रिंग के लिए स्वरूपित बाइट्स

आपके पास "स्वरूपित बाइट्स" नहीं है। आपके पास बाइट्स हैं । आपको बेस-एन (आमतौर पर: बेस -64) एनकोड की तरह कुछ का उपयोग करने की आवश्यकता है। यह स्थानान्तरण करता है

  • एक स्वरूपित स्ट्रिंग को बाइट्स मनमाना
  • मूल बाइट्स के लिए एक स्वरूपित स्ट्रिंग

Convert.ToBase64String और कन्वर्ट देखें। FromBase64String


1
क्या आप BinaryFormatterइस अजीब उदाहरण के समान एक का उपयोग कर सकते हैं ?
ड्रॉज़ौस

@drzaus hm ... शायद नहीं:> "द्विआधारी क्रमांकन में कोई भी अनपेक्षित सरोगेट पात्र खो गए हैं"
drzaus

210

मैंने अभी यह परीक्षण किया है और ठीक काम करता है।

string test = "Testing 1-2-3";

// convert string to stream
byte[] byteArray = Encoding.ASCII.GetBytes(test);
MemoryStream stream = new MemoryStream(byteArray);

// convert stream to string
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();

यदि आपको streamपहले ही लिखा जा चुका है, तो आप पाठ को पढ़ने से पहले सबसे पहले शुरुआत करना चाहते हैं:stream.Seek(0, SeekOrigin.Begin);


और StreamReader रीडर = new StreamReader (स्ट्रीम) के आसपास एक ब्लॉकिंग ब्लॉक का उपयोग न करें;
PRMan

7

स्ट्रिंग रूपांतरण में UTF8 मेमोरीस्ट्रीम:

var res = Encoding.UTF8.GetString(stream.GetBuffer(), 0 , (int)stream.Length)

2
इसके बजाय ToArray () का उपयोग करें। बफर इस्तेमाल किए गए डेटा के आकार से बड़ा हो सकता है। ToArray () सही आकार के साथ डेटा की एक प्रति लौटाता है। var array = stream.ToArray(); var str = Encoding.UTF8.GetString(array, 0, array.Length);Msdn.microsoft.com/en-us/library/…
Mortennobel

1
@Mortennobel ToArray()मेमोरी में एक नया एरे आवंटित करता है और बफर से अधिक डेटा कॉपी करता है, जो कि बहुत सारे डेटा के साथ काम करने पर गंभीर प्रभाव पड़ सकता है।
लेवी मोटेलो

स्ट्रीम के उपयोग पर ध्यान दें। स्ट्रीम के बजाय। स्पीड। लंबाई ()। और लेवी ने सही तरीके से ToArray () का उपयोग न करने का कारण नोट किया।
वोल्फगैंग ग्रिनफेल्ड

5

जब आप UTF8नीचे की तरह एनकोड स्ट्रीम के साथ परीक्षण का प्रयास करते हैं

var stream = new MemoryStream();
var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);
Serializer.Serialize<SuperExample>(streamWriter, test);

5

इसे इस्तेमाल करे।

string output1 = Encoding.ASCII.GetString(byteArray, 0, byteArray.Length)

2

मैंने किसी भी कार्रवाई को कॉल करने के लिए एक उपयोगी विधि लिखी जो एक लेता है StreamWriterऔर इसे एक स्ट्रिंग के बजाय बाहर लिखता है। विधि इस तरह है;

static void SendStreamToString(Action<StreamWriter> action, out string destination)
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream, Encoding.Unicode))
    {
        action(writer);
        writer.Flush();
        stream.Position = 0;
        destination = Encoding.Unicode.GetString(stream.GetBuffer(), 0, (int)stream.Length);
    }
}

और आप इसे इस तरह से उपयोग कर सकते हैं;

string myString;

SendStreamToString(writer =>
{
    var ints = new List<int> {1, 2, 3};
    writer.WriteLine("My ints");
    foreach (var integer in ints)
    {
        writer.WriteLine(integer);
    }
}, out myString);

मुझे पता है कि यह एक के साथ बहुत आसान हो सकता है StringBuilder, मुद्दा यह है कि आप किसी भी विधि को कॉल कर सकते हैं जो ए लेता है StreamWriter


1

मैं वस्तुओं को स्ट्रिंग में क्रमबद्ध करना चाहता हूं, और वापस।

अन्य उत्तरों से भिन्न, लेकिन अधिकांश ऑब्जेक्ट प्रकारों के लिए वास्तव में ऐसा करने का सबसे सरल तरीका XmlSerializer है:

        Subject subject = new Subject();
        XmlSerializer serializer = new XmlSerializer(typeof(Subject));
        using (Stream stream = new MemoryStream())
        {
            serializer.Serialize(stream, subject);
            // do something with stream
            Subject subject2 = (Subject)serializer.Deserialize(stream);
            // do something with subject2
        }

समर्थित प्रकारों के आपके सभी सार्वजनिक गुणों को क्रमबद्ध किया जाएगा। यहां तक ​​कि कुछ संग्रह संरचनाओं का समर्थन किया जाता है, और उप-ऑब्जेक्ट गुणों के लिए नीचे सुरंग जाएगा। आप यह नियंत्रित कर सकते हैं कि आपके गुणों पर विशेषता के साथ क्रमांकन कैसे काम करता है ।

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


0

Usecase में जहाँ आप POCOs को क्रमबद्ध / डिसेरियलाइज़ करना चाहते हैं, न्यूटनसॉफ्ट की JSON लाइब्रेरी वास्तव में अच्छी है। मैं इसे SQL सर्वर के भीतर POCO को जारी रखने के लिए उपयोग करता हूं क्योंकि JSON एक nvarchar फ़ील्ड में स्ट्रिंग करता है। कैविएट यह है कि चूँकि यह सच नहीं है, इसलिए यह निजी / संरक्षित सदस्यों और वर्ग पदानुक्रम को संरक्षित नहीं करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.