C# 小敘 Encoding (二).NET(C#):字元編碼(Encoding)和位元組順序標記(BOM)

來源:互聯網
上載者:User
Encoding用法

Encoding用法比較簡單,如果只是位元組和字元的互相轉換,GetBytes()和GetChars()這兩個方法及它們的重載基本上會滿足你所有要求。

GetByteCount()及其重載是得到一個字串轉換成位元組時實際的位元組個數。

GetCharCount()及其重載是得到一個位元組數群組轉換成字串的大小。

要注意這兩個方法:int GetMaxByteCount(int charCount); int GetMaxCharCount(int byteCount);

它並不是你期望的那樣,如果是單位元組就返回charCount,如果是雙位元組就返回chartCount*2,而是chartCount+1,(chartCount+1)*2。

            Console.WriteLine("The max byte count is {0}.", Encoding.Unicode.GetMaxByteCount(10));            Console.WriteLine("The max byte count is {0}.", Encoding.ASCII.GetMaxByteCount(10));

上面的結果分別是22和11,而不是20,10。我在一篇英文部落格裡找到了原因,我英語不好,沒有弄明白什麼是high surrogate和low surrogate:http://blogs.msdn.com/b/shawnste/archive/2005/03/02/383903.aspx

       For example, Encoding.GetEncoding(1252).GetMaxByteCount(1) returns 2.  1252 is a single byte code page (encoding), so generally one would expect that GetMaxByteCount(n) would return n, but it doesn't, it usually returns n+1.

     One reason for this oddity is that an Encoder could store a high surrogate on one call to GetBytes(), hoping that the next call is a low surrogate.  This allows the fallback mechanism to provide a fallback for a complete surrogate pair, even if that pair is split between calls to GetBytes().  If the fallback returns a ? for each surrogate half, or if the next call doesn't have a surrogate, then 2 characters could be output for that surrogate pair.  So in this case, calling Encoder.GetBytes() with a high surrogate would return 0 bytes and then following that with another call with only the low surrogate would return 2 bytes.

下面代碼是Encoding的簡單應用,大家可以列印一下結果,然後結合上篇講的,會有所收穫的。

        static void Output(Encoding encoding,string t)        {            Console.WriteLine(encoding.ToString());            byte[] buffer = encoding.GetBytes(t);            foreach (byte b in buffer)            {                Console.Write(b + "-");            }            string s = encoding.GetString(buffer);            Console.WriteLine(s);        }
            string strTest = "test我鎔a有κ";            Console.WriteLine(strTest);            Output(Encoding.GetEncoding("gb18030"), strTest);            Output(Encoding.Default, strTest);            Output(Encoding.UTF32, strTest);            Output(Encoding.UTF8, strTest);            Output(Encoding.Unicode, strTest);            Output(Encoding.ASCII, strTest);            Output(Encoding.UTF7, strTest);
關於BOM

BOM全稱是Byte Order Mark,即位元組順序標記,是一段二進位,用於標識一個文本是用什麼編碼的,比如當用Notepad開啟一個文本時,如果文本裡包括這一段BOM,那麼它就能判斷是採用哪一種編碼方式,並用相應的解碼方式,就會正確開啟文本不會有亂碼。如果沒有這一段BOM,Notepad會預設以ANSI開啟,這種會有亂碼的可能性。可以通過Encoding的方法GetPreamble()來判斷這編碼有沒有BOM,目前CLR中只有下面5個Encoding有BOM。

UTF-8: EF BB BF

UTF-16 big endian: FE FF

UTF-16 little endian: FF FE

UTF-32 big endian: 00 00 FE FF

UTF-32 little endian: FF FE 00 00

用Encoding的靜態屬性Unicode,UTF8,UTF32構造的Encoding都是預設帶有BOM的,如果你想在寫一個文本時(比如XML檔案,如果有BOM,會有亂碼的),不想帶BOM,那麼就必須用它們的執行個體,

Encoding encodingUTF16=new UnicodeEncoding(false, false);//第二個參數必須要為falseEncoding encodingUTF8=new UTF8Encoding(false);Encoding encodingUTF32=new UTF32Encoding(false,false);//第二個參數必須要為false

 讀寫文本和BOM的關係可以參考園子裡這篇部落格,講的很詳細我就不重複了,.NET(C#):字元編碼(Encoding)和位元組順序標記(BOM)

  判斷一個文本的編碼方式

如果給定一個文本,我們不知道它的編碼格式,解碼時我們如何選擇Encoding呢?答案是根據BOM來判斷到底是哪種Unicode,如果沒有BOM,這個就很難說了,這個得根據文字檔的來源了,一般是用Encoding.Default,這個是根據你電腦裡當前的設定而返回不同的值。如果你的檔案是來自一位國際友人的話,你最好用UTF-8來解碼了。下面的代碼在指定檔案沒有BOM時,不能保證其正確性,如果你要用到你項目中,千萬要注意這一點。

/// <summary>        ///Return the Encoding of a text file.  Return Encoding.Default if no Unicode        // BOM (byte order mark) is found.        /// </summary>        /// <param name="FileName"></param>        /// <returns></returns>        public static Encoding GetFileEncoding(String FileName)        {            Encoding Result = null;            FileInfo FI = new FileInfo(FileName);            FileStream FS = null;            try            {                FS = FI.OpenRead();                Encoding[] UnicodeEncodings =                {                     Encoding.BigEndianUnicode,                     Encoding.Unicode,                    Encoding.UTF8,                    Encoding.UTF32,                    new UTF32Encoding(true,true)                };                for (int i = 0; Result == null && i < UnicodeEncodings.Length; i++)                {                    FS.Position = 0;                    byte[] Preamble = UnicodeEncodings[i].GetPreamble();                    bool PreamblesAreEqual = true;                    for (int j = 0; PreamblesAreEqual && j < Preamble.Length; j++)                    {                        PreamblesAreEqual = Preamble[j] == FS.ReadByte();                    }                    // or use Array.Equals to compare two arrays.                    // fs.Read(buf, 0, Preamble.Length);                    // PreamblesAreEqual = Array.Equals(Preamble, buf)                    if (PreamblesAreEqual)                    {                        Result = UnicodeEncodings[i];                    }                }            }            catch (System.IO.IOException ex)            {                throw ex;            }            finally            {                if (FS != null)                {                    FS.Close();                }            }            if (Result == null)            {                Result = Encoding.Default;            }            return Result;        }

待續。。。。

下一節主要講Encoder和Decoder

順便問一下,編輯部落格時,看著還挺漂亮的文章,怎麼預覽時好多格式都不見了?好難看啊

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.