2013-07-23 7 views
104

मैं ऑब्जेक्ट्स को तारों को क्रमबद्ध करना चाहता हूं, और पीछे।स्ट्रीम को स्ट्रिंग और पीछे कनवर्ट करना ... हम क्या खो रहे हैं?

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

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

हमारे तरीके:

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); 
+0

स्पष्टीकरण के लिए संपादित, ty। – flipuhdelphia

+0

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

उत्तर

46

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

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

को

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

    • मनमाना बाइट्स स्थानांतरित करता है। FromBase64String

    +1

    क्या आप एक ['बाइनरीफॉर्मेटर'] (http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter (v = vs.110) .aspx) का उपयोग कर सकते हैं, समान इस [अजीब उदाहरण] (http://stackoverflow.com/a/1133465/1037948) के लिए? – drzaus

    +0

    @drzaus hm ... शायद नहीं:> "किसी भी unpaired सरोगेट वर्ण बाइनरी serialization में खो गए हैं" – drzaus

    +15

    वैसे यह पहला @drzaus है ... कभी भी किसी को एसओ पर खुद से बात नहीं देखा। –

    121

    मैं सिर्फ यह परीक्षण किया है और ठीक काम करता है है।

    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);

    5

    जब आप

    नीचे
    var stream = new MemoryStream(); 
    var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8); 
    Serializer.Serialize<SuperExample>(streamWriter, test); 
    
    तरह UTF8 एनकोड धारा के साथ कोशिश का परीक्षण
    3

    इसे आज़माएं।

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

    USECASE जहां क्रमानुसार/deserialize Pocos करना चाहते हैं, Newtonsoft के JSON पुस्तकालय वास्तव में अच्छा है। मैं इसे SQL सर्वर के भीतर POCO को nvarchar फ़ील्ड में JSON स्ट्रिंग के रूप में जारी रखने के लिए उपयोग करता हूं। चेतावनी यह है कि चूंकि यह सही/deialization नहीं है, यह निजी/संरक्षित सदस्यों और वर्ग पदानुक्रम को संरक्षित नहीं करेगा।

    4

    स्ट्रिंग रूपांतरण के लिए एक UTF8 MemoryStream:

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

    इसके बजाय ToArray() का उपयोग करें। बफर प्रयुक्त डेटा के आकार से बड़ा हो सकता है। ToArray() सही आकार के साथ डेटा की एक प्रति देता है। 'var array = stream.ToArray(); var str = एन्कोडिंग .UTF8.GetString (सरणी, 0, सरणी। लम्बाई); '। यह भी देखें https://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx?ranMID=24542&ranEAID=TnL5HPStwNw&ranSiteID=TnL5HPStwNw-fWxoHnp968IcSsgF87gs3g&tduid=(af5d64506773ff2a87e3cde51de009eb)(256380)(2459594)(TnL5HPStwNw- fWxoHnp968IcSsgF87gs3g)() – Mortennobel

    0

    मैं एक उपयोगी विधि लिखा था किसी भी कार्रवाई है कि एक 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 लेता कॉल कर सकते हैं है।

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