2010-05-26 13 views
15

मुझे विजुअल स्टूडियो 2010 का उपयोग कर सी # 4.0 में यूनिट टेस्ट में स्ट्रिंग की तुलना में समस्या हो रही है। यह वही टेस्ट केस विजुअल स्टूडियो 2008 (सी # 3.5 के साथ) में ठीक से काम करता है।स्ट्रिंग तुलना में यूटीएफ -8 बाइट ऑर्डर मार्कर को मैं कैसे अनदेखा कर सकता हूं?

byte[] rawData = GetData(); 
string data = Encoding.UTF8.GetString(rawData); 

Assert.AreEqual("Constant", data, false, CultureInfo.InvariantCulture); 

इस परीक्षण डीबगिंग, वहीं data स्ट्रिंग नग्न आंखों के लिए प्रकट होता है वास्तव में शाब्दिक रूप में एक ही स्ट्रिंग को रोकने के लिए:

यहाँ प्रासंगिक कोड का टुकड़ा है। जब मैंने data.ToCharArray() कहा, मैंने देखा कि स्ट्रिंग data का पहला बाइट मूल्य 65279 है जो यूटीएफ -8 बाइट ऑर्डर मार्कर है। मुझे समझ में नहीं आता है कि क्यों Encoding.UTF8.GetString() इस बाइट को चारों ओर रखता है।

मैं Encoding.UTF8.GetString() से कैसे परिणामस्वरूप स्ट्रिंग में बाइट ऑर्डर मार्कर डाल सकता हूं?

अद्यतन: समस्या यह थी कि GetData(), जो डिस्क से एक फ़ाइल में लिखा है, FileStream.readbytes() का उपयोग कर फ़ाइल से डेटा पढ़ता है। मैंने इसे StreamReader का उपयोग करके और स्ट्रिंग को Encoding.UTF8.GetBytes() का उपयोग करके बाइट्स में परिवर्तित करके सही किया है, जो कि पहले स्थान पर किया जाना चाहिए था! पूरी सहायताके लिए शुक्रिया।

+1

यदि आप एक छोटे, लेकिन पूरा, कार्यक्रम है कि समस्या को दर्शाता है पोस्ट कर सकते हैं? –

उत्तर

16

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

संपादित करें: वैकल्पिक रूप से, आप डिकोडिंग करने के लिए StreamReader का उपयोग कर सकते हैं। यहाँ एक उदाहरण है, एक ही बाइट सरणी दिखाता है के माध्यम से एक StreamReaderEncoding.GetString या एक चरित्र का उपयोग कर दो अक्षर में परिवर्तित किया जा रहा:

using System; 
using System.IO; 
using System.Text; 

class Test 
{ 
    static void Main() 
    { 
     byte[] withBom = { 0xef, 0xbb, 0xbf, 0x41 }; 
     string viaEncoding = Encoding.UTF8.GetString(withBom); 
     Console.WriteLine(viaEncoding.Length); 

     string viaStreamReader; 
     using (StreamReader reader = new StreamReader 
       (new MemoryStream(withBom), Encoding.UTF8)) 
     { 
      viaStreamReader = reader.ReadToEnd();   
     } 
     Console.WriteLine(viaStreamReader.Length); 
    } 
} 
+0

आप सही हैं कि कच्चे डेटा में बीओएम शामिल है। ऐसा नहीं होना चाहिए, इसलिए मैं उस भाग को ठीक कर रहा हूं। एक दार्शनिक अनुवर्ती प्रश्न: 'स्ट्रिंग.इक्वाल्स 'विधि क्यों बीओएम को ध्यान में रखती है? एक स्ट्रिंग तुलना करने या मेटाडेटा के रूप में इलाज करते समय स्ट्रिंग के "मांस" के रूप में नहीं, यह केवल अनदेखा क्यों नहीं किया जाता है? – Skrud

+1

@ स्क्राउड: आपके पास विशिष्ट चरित्र अनुक्रम हैं। कच्ची स्ट्रिंग। एक्वाल्स विधि क्रमिक अनुक्रमों की तुलना करता है, बिना किसी विचार के। यह संभव है कि उपलब्ध कुछ अन्य स्ट्रिंग तुलना (संस्कृति जागरूक इत्यादि) बीओएम को अनदेखा कर सकती हैं - मुझे यकीन नहीं है। यह देखते हुए कि यह कुछ तरीकों से एक अजीब चरित्र है, मैं वास्तव में आश्वस्त नहीं हूं कि इसे मनमाने ढंग से अनदेखा करना उचित है। इसे इस तरह से रखें: समानता विफलता से पता चला है कि आपके पास कुछ खराब डेटा था, इसलिए व्यवहार ने आपको अपना कोड सुधारने का नेतृत्व किया है। यह एक अच्छी बात है, नहीं? –

+1

बिल्कुल। पहली जगह परीक्षण का बिंदु कौन सा है। :-) – Skrud

-3

मेरा मानना ​​है कि अगर आप ट्रिम (अतिरिक्त चरित्र निकाल दिया जाता है) डीकोड स्ट्रिंग

+0

यह काम नहीं करता है ... – wlscaudill

6

वहाँ StreamReader और MemoryStream बनाने की तुलना में यह करने के लिए एक से थोड़ा अधिक प्रभावी हो सकता है:

1) क्या आप जानते हैं हमेशा एक बीओएम

string viaEncoding = Encoding.UTF8.GetString(withBom, 3, withBom.Length - 3); 
है कि वहाँ तो

2) यदि आप नहीं जानते हैं, तो देखें:

string viaEncoding; 
if (withBom.Length >= 3 && withBom[0] == 0xEF && withBom[1] == 0xBB && withBom[2] == 0xBF) 
    viaEncoding = Encoding.UTF8.GetString(withBom, 3, withBom.Length - 3); 
else 
    viaEncoding = Encoding.UTF8.GetString(withBom); 
संबंधित मुद्दे