2011-03-10 16 views
44

मुझे स्ट्रीमवाइटर और बाइट ऑर्डर मार्क्स के साथ कोई समस्या है। प्रलेखन यह बताता है कि एन्कोडिंग.यूटीएफ 8 एन्कोडिंग में बाइट ऑर्डर अंक सक्षम हैं लेकिन जब फाइलें लिखी जा रही हैं तो कुछ के निशान हैं जबकि अन्य नहीं हैं।स्ट्रीमवाइटर और यूटीएफ -8 बाइट ऑर्डर मार्क्स

मैं निम्नलिखित तरीके से धारा लेखक बना रहा हूं:

this.Writer = new StreamWriter(this.Stream , System.Text.Encoding.UTF8); 

क्या हो रहा हो सकता सराहना की होगी पर कोई भी विचार।

+1

ध्यान दें कि, जबकि तकनीकी रूप से UTF-8 में अनुमति दी है, एक बीओएम न की आवश्यकता है या यूनिकोड द्वारा सिफारिश की है ([रेफरी] को देखने के (http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf))। एक बात के लिए, यह बेकार है (कहने के लिए, यूटीएफ -16 के विपरीत) - यूटीएफ -8 बाइट ऑर्डर मानक द्वारा निर्दिष्ट किया गया है। दूसरे के लिए, यह पाठ प्रसंस्करण को खराब कर सकता है। उदाहरण के लिए, एक्सएमएल प्रोलॉग से पहले कोई अक्षर होने पर कई एक्सएमएल पार्सर्स चकित होंगे। –

+1

क्या आप वाकई सुनिश्चित हैं कि आप यूटीएफ 8 निर्दिष्ट कर रहे हैं? क्योंकि यदि आप इसे निर्दिष्ट नहीं करते हैं, तो यह अभी भी एक यूटीएफ 8 लिखेगा, लेकिन यूनिकोड मानक 5.0 से बीओएम – xanatos

+0

के बिना * यूनिकोड मानक भी को प्रारंभिक बाइट ऑर्डर मार्क (बीओएम) का उपयोग स्पष्ट रूप से बड़े- यूनिकोड एन्कोडिंग योजनाओं में से कुछ में एंडियन या थोड़ा एंडियन डेटा। * –

उत्तर

5

क्या आप प्रत्येक फ़ाइल के लिए StreamWriter के समान निर्माता का उपयोग करते हैं? क्योंकि प्रलेखन कहते हैं:

एक StreamWriter UTF-8 एन्कोडिंग और एक बीओएम का उपयोग कर बनाने के लिए, एक निर्माता है कि इस तरह StreamWriter (स्ट्रिंग, बूलियन, एन्कोडिंग) के रूप में एन्कोडिंग, निर्दिष्ट करता है काम में लें।

मैं थोड़ी देर पहले इसी तरह की स्थिति में था। मैं StreamWriter के बजाय Stream.Write विधि का उपयोग कर समाप्त हो गया और Encoding.GetBytes(stringToWrite)

11

केवल समय मैंने देखा है कि निर्माता जोड़ नहीं UTF-8 बीओएम है लिखने से पहले Encoding.GetPreamble() का परिणाम लिखा है, तो धारा स्थिति 0 पर नहीं है जब आप इसे कहते हैं। उदाहरण के लिए, नीचे दिए गए कोड में, बीओएम नहीं लिखा है:

using (var s = File.Create("test2.txt")) 
{ 
    s.WriteByte(32); 
    using (var sw = new StreamWriter(s, Encoding.UTF8)) 
    { 
     sw.WriteLine("hello, world"); 
    } 
} 

के रूप में अन्य लोगों, ने कहा है कि आप, StreamWriter(stream) निर्माता उपयोग कर रहे हैं एन्कोडिंग निर्दिष्ट किए बिना, तो आप बीओएम नहीं देख सकेंगे।

0

क्या आप एक ऐसी स्थिति दिखा सकते हैं जहां यह इसका उत्पादन न करे? एकमात्र मामला जहां प्रस्तावना मौजूद नहीं है, मुझे यह पता चल सकता है कि जब लेखक को कुछ भी लिखा नहीं जाता है (जिम मिशेल एक अन्य, तार्किक और आपकी समस्या होने की अधिक संभावना है, तो इसका उत्तर देखें)।

मेरे परीक्षण कोड:

var stream = new MemoryStream(); 
using(var writer = new StreamWriter(stream, System.Text.Encoding.UTF8)) 
{ 
    writer.Write('a'); 
} 
Console.WriteLine(stream.ToArray() 
    .Select(b => b.ToString("X2")) 
    .Aggregate((i, a) => i + " " + a) 
    ); 
2

लगता है कि यदि फ़ाइल पहले से ही अस्तित्व में है और बीओएम शामिल नहीं किया है, तो यह बीओएम में शामिल होंगे नहीं जब ओवरराइट, दूसरे शब्दों StreamWriter बीओएम को बरकरार रखता है में (या इसके अभाव है) जब एक फाइल ओवरराइटिंग।

61

जैसा कि किसी ने पहले ही बताया है कि एन्कोडिंग तर्क के बिना कॉल करना चाल है। हालांकि, अगर आप स्पष्ट होना चाहता हूँ, इस प्रयास करें:

using (var sw = new StreamWriter("text.txt", new UTF8Encoding(false))) 

कुंजी बजाय Encoding.UTF8Encoding का उपयोग कर के, एक नया UTF8Encoding (गलत) के निर्माण के लिए है। अगर बीओएम जोड़ा जाना चाहिए या नहीं तो यह नियंत्रित करना है।

यह स्ट्रीमवाइटर को एन्कोडिंग तर्क के बिना कॉल करने जैसा ही है, आंतरिक रूप से यह वही काम कर रहा है।

13

समस्या इस तथ्य के कारण है कि आप Encoding class पर स्थिर UTF8 property का उपयोग कर रहे हैं।

GetPreamble methodEncoding वर्ग UTF8 संपत्ति द्वारा लौटाए के कहने पर बुलाया है, यह बाइट क्रम चिह्न रिटर्न (तीन अक्षरों का बाइट सरणी) और किसी भी अन्य सामग्री के लिए लिखा है से पहले धारा में लिखा है धारा (एक नई धारा मानते हुए)।

आप UTF8Encoding class का उदाहरण बनाकर खुद के द्वारा इस से बच सकते हैं, तो जैसे:

// As before. 
this.Writer = new StreamWriter(this.Stream, 
    // Create yourself, passing false will prevent the BOM from being written. 
    new System.Text.UTF8Encoding()); 

default parameterless constructor (जोर मेरा) के लिए प्रलेखन के अनुसार:

यह निर्माता एक उदाहरण बनाता है कि यूनिकोड बाइट ऑर्डर मार्क प्रदान नहीं करता है और जब कोई अमान्य एन्कोडिंग पता चला है तो अपवाद नहीं फेंकता है।

इसका मतलब है कि GetPreamble करने के लिए कॉल एक खाली सरणी वापस आ जाएगी, और इसलिए कोई बीओएम अंतर्निहित धारा में लिखा जाएगा।

+0

एन्कोडिंग हमारे प्रोग्राम में एक उपयोगकर्ता सेटिंग है (जो टीसीपी पर टेक्स्ट संदेश भेजती है) ... इसे 'एन्क = एन्कोडिंग। गेटएन्कोडिंग (...)' के साथ एक साधारण पार्स से पुनर्प्राप्त किया जाता है। मेरे आस-पास का एकमात्र तरीका वास्तव में 'अगर (एनटी यूटीएफ 8 एन्कोडिंग) एएन = नया यूटीएफ 8 एन्कोडिंग (झूठा) जोड़ना था; इसके पीछे। हालांकि, एक सुंदर गंदा फिक्स, लेकिन मुझे इसे हल करने का कोई और तरीका नहीं दिखता है ... – Nyerguds

+0

@Nyerguds यह एकमात्र तरीका नहीं है। आप एन्कोडिंग को एक इंटरफ़ेस में प्राप्त करने के लिए अमूर्त कर सकते हैं जो पैरामीटर दिया जाता है, एन्कोडिंग प्राप्त करता है। फिर आप अपने कोड में उस इंटरफ़ेस के कार्यान्वयन को पास/इंजेक्ट करते हैं। यह सब कुछ साफ करता है। – casperOne

+0

कि थोड़े ही एक ही चीज को एक अलग वर्ग में ले जाता है। कुल मिलाकर, मुझे यह बिल्कुल विचित्र लगता है कि GetEncoding किसी भी तरह से डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग न करने का प्रबंधन करता है। ठीक है। – Nyerguds

9

मेरा उत्तर हैलोसम के एक पर आधारित है जिसमें सभी आवश्यक जानकारी शामिल है। केवल मुझे विश्वास है कि ओपी क्या मांग रहा है यह सुनिश्चित करने के लिए कि बीओएम फ़ाइल में उत्सर्जित हो।

तो यूटीएफ 8 एन्कोडिंग सीटीआर को झूठ बोलने की बजाय आपको सच होने की आवश्यकता है।

using (var sw = new StreamWriter("text.txt", new UTF8Encoding(true))) 

नीचे कोड की कोशिश करो, एक हेक्स संपादक में जिसके परिणामस्वरूप फ़ाइलों को खोलने और देखो, जो एक बीओएम होता है और जो नहीं करता है।

class Program 
{ 
    static void Main(string[] args) 
    { 
     const string nobomtxt = "nobom.txt"; 
     File.Delete(nobomtxt); 

     using (Stream stream = File.OpenWrite(nobomtxt)) 
     using (var writer = new StreamWriter(stream, new UTF8Encoding(false))) 
     { 
      writer.WriteLine("HelloПривет"); 
     } 

     const string bomtxt = "bom.txt"; 
     File.Delete(bomtxt); 

     using (Stream stream = File.OpenWrite(bomtxt)) 
     using (var writer = new StreamWriter(stream, new UTF8Encoding(true))) 
     { 
      writer.WriteLine("HelloПривет"); 
     } 
    } 
3

मैंने पाया इस उत्तर उपयोगी (@Philipp Grathwohl और @Nik करने के लिए धन्यवाद), लेकिन मेरे मामले में मैं FileStream उपयोग कर रहा हूँ कार्य को पूरा करने, इसलिए, कोड है कि बीओएम उत्पन्न करता है इस प्रकार है:

using (FileStream vStream = File.Create(pfilePath)) 
{ 
    // Creates the UTF-8 encoding with parameter "encoderShouldEmitUTF8Identifier" set to true 
    Encoding vUTF8Encoding = new UTF8Encoding(true); 
    // Gets the preamble in order to attach the BOM 
    var vPreambleByte = vUTF8Encoding.GetPreamble(); 

    // Writes the preamble first 
    vStream.Write(vPreambleByte, 0, vPreambleByte.Length); 

    // Gets the bytes from text 
    byte[] vByteData = vUTF8Encoding.GetBytes(pTextToSaveToFile); 
    vStream.Write(vByteData, 0, vByteData.Length); 
    vStream.Close(); 
} 
+1

मुझे ज्यादातर 'नया यूटीएफ 8 एन्कोडिंग (सत्य)' कन्स्ट्रक्टर पता करने के लिए उपयोगी पाया गया। –

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