国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
漫談.NET開(kāi)發(fā)中的字符串編碼
漫談.NET開(kāi)發(fā)中的字符串編碼
說(shuō)明:
         在《 .NET 4.0面向?qū)ο缶幊搪?》基礎(chǔ)篇《 13.2.1 序列化與流》中,向大家介紹了如何向流中序列化一個(gè)對(duì)象。
         本篇擴(kuò)充閱讀將向讀者介紹將字符串對(duì)象的序列化,這里面的關(guān)鍵是字符串應(yīng)該如何編碼和解碼為二進(jìn)制數(shù)值,從而可以把它們保存到文件流( FileStream)中,或者通過(guò)網(wǎng)絡(luò)流( NetworkStream)將它們遠(yuǎn)程發(fā)送到另一臺(tái)計(jì)算機(jī)上。
抱怨一下:
     使用CSDN的在線編輯器寫(xiě)文章是一個(gè)讓人望而生畏的工作,當(dāng)提交文檔時(shí),CSDN Web服務(wù)器經(jīng)常報(bào)告“內(nèi)部錯(cuò)誤”,所以文章排版不好,諸位見(jiàn)諒。博客園的系統(tǒng)穩(wěn)定些,讀者可以訪問(wèn)http://www.cnblogs.com/bitfan/archive/2010/11/25/1887590.html 看到排版好一點(diǎn)的同樣文章。
 

 ==============================================================       
1 引子
         在實(shí)際開(kāi)發(fā)中,經(jīng)常需要將一些字符串寫(xiě)入到文本文件中,或者從文本文件中讀入字符串,在 .NET應(yīng)用程序中,通常使用 StreamReader或 StreamWriter兩個(gè)類(lèi)完成這一工作,比如以下代碼將 fileContent字串寫(xiě)入到 FileName文件中:
static   void  WriteFileUseStreamWriter(String fileContent, String FileName)
{
  using  (StreamWriter writer  =   new  StreamWriter(FileName))
  {
    writer.Write(fileContent);
  }
}
如果你使用 .NET基類(lèi)庫(kù)中相關(guān)類(lèi)(比如 StreamReader或下面用到的 File類(lèi))去讀取這個(gè)文件,你會(huì)發(fā)現(xiàn)一切如你所愿地正常運(yùn)轉(zhuǎn):
WriteFileUseStreamWriter( " 中國(guó)ab " ,  " test.txt " );
Console.WriteLine(File.ReadAllText( " test.txt " ));      // 輸出:“中國(guó)ab”  
       
    由于多數(shù)情況下我們都工作在中文 Windows下,而且往往都是某個(gè) .NET程序?qū)?,另一個(gè) .NET程序讀,所以,不少 .NET程序員可能都沒(méi)注意到這其中其實(shí)存在著一個(gè)字符編碼的問(wèn)題,在特定的場(chǎng)合下,這一問(wèn)題會(huì)給我們帶來(lái)麻煩。
         請(qǐng)看圖 1:
 

 圖1 記事本支持的編碼方式
         默認(rèn)情況下, Windows記事本以 ANSI編碼方式保存文件。如圖 1所示,如果文本內(nèi)容為“中國(guó) ab ” ,記事本將其以 ASNI方式保存為“ test.txt”,則以下代碼將“罷工”了(參看圖 2):
Console.WriteLine(File.ReadAllText( " test.txt " ));
      

  
圖2 漢字將顯示為亂碼
         如 圖 2 所示, File.ReadAllText方法打開(kāi)“ test.txt”文件時(shí),會(huì)發(fā)現(xiàn)英文字符可以正常顯示,但中文將顯示為亂碼。
2 了解字符的編碼
         我們可以做個(gè)試驗(yàn),使用記事本將“中國(guó) ab”這個(gè)中英混雜的字符串以不同編碼方式保存為多個(gè)“ .txt”文件,然后直接查看其二進(jìn)制內(nèi)容:
 
 圖3   比對(duì)字符編碼
 

          圖 3 展示了“中國(guó) ab”按四種編碼方式( ANSI、 UTF8、 Unicode、 Unicode Big Endian )得到的不同二進(jìn)制數(shù)據(jù)。
         以英文字符“ a”為例, ANSI和 UTF8得到的數(shù)值都是“ 61”,但 Unicode將它擴(kuò)充為 2個(gè)字節(jié) 16位的二進(jìn)制(“ 61 00”和“ 00 61”),所以我們又將這種編碼方式稱(chēng)為 UTF-16。
         UTF-16 又可以細(xì)分為 2種編碼方式: Big Endian方式與 Little_Edian方式,這兩者的唯一區(qū)別在于字節(jié)排列順序剛好相反, Little_Edian方式將“ a”編碼為“ 61 00”,而 Big Endian方式則編碼為“ 00 61”。
         現(xiàn)在看看中文字符,“中國(guó)”兩個(gè)漢字, ANSI編碼為“ D6 D0 B9 FA”, 4個(gè)字節(jié),一個(gè)漢字占兩個(gè)字節(jié),而 UTF8則編碼為“ E4 B8 AD E5 9B BD”, 6個(gè)字節(jié),一個(gè)漢字占 3個(gè)字節(jié)!這說(shuō)明 UTF8是一種“變長(zhǎng)”的編碼,可能使用 1~4個(gè)字節(jié)來(lái)表示某個(gè)字符。
         另外,我們看到 UTF8和 Unicode編碼(不管是 Big Endian還是 Little Endian )前面都有幾個(gè)標(biāo)記字符,這些字符放在文本文件的開(kāi)頭,稱(chēng)為“ BOM( Byte Order Mark,字節(jié)順序標(biāo)記)”指明了文本的編碼方式,以下是 .NET程序中常見(jiàn)的字符編碼方式的 BOM值:
 
編碼
 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
 

 
 
         了解了上述基礎(chǔ)知識(shí),我們就可以依據(jù) BOM值自動(dòng)檢測(cè)字符串的編碼方式,從而正確從二進(jìn)制數(shù)據(jù)流中解碼,以下代碼檢測(cè)文本二進(jìn)制數(shù)據(jù)是否采用 UTF8編碼:
 
// 打開(kāi)文件讀取二進(jìn)制數(shù)據(jù)
byte [] FileContents  =  File.ReadAllBytes(FilePath);
int  filelength  =  FileContents.Length;
// 檢測(cè)BOM
if  (FileContents[ 0 ]  ==   0xef   &&  FileContents[ 1 ]  ==   0xbb &&  FileContents[ 2 ]  ==   0xbf )

    // 按UTF8解碼字符串,注意要排除掉BOM占用的3個(gè)字節(jié)。
   String content =  Encoding.UTF8.GetString( FileContents,  3 , filelength  -   3 );
   Console.WriteLine(content);
}
         其他的編碼方式都可以“依樣畫(huà)葫蘆”。
3 詳解 .NET 基類(lèi)庫(kù)中與字符編碼相關(guān)的類(lèi)
         前述代碼中的 Encoding類(lèi)是 .NET實(shí)現(xiàn)字符編碼解碼的核心類(lèi)型。圖 4展示了它的屬性:
 
圖 4 Encoding類(lèi)型
         如圖 4所示, Encoding類(lèi)型提供了 UTF8、 Unicode等編碼和解碼器,調(diào)用它的 Get系列方法完成編碼和解碼工作,以下為示例代碼:
 
// 編碼
byte [] bytes  =  Encoding.UTF8.GetBytes( " 中國(guó)ab " );
foreach  ( byte  value  in  bytes)
   Console.Write( "  {0} " , value.ToString( " x " ));  // 轉(zhuǎn)化為16進(jìn)制
Console.WriteLine();
// 解碼
char [] chars  =  Encoding.UTF8.GetChars(bytes);
foreach  ( char  ch  in  chars)
    Console.Write( "  {0} " , ch);
運(yùn)行結(jié)果如下:
 
圖5 編碼和解碼
         需要注意的是上述二進(jìn)制值不包括 BOM。
         事實(shí)上, .NET中的 StreamWriter默認(rèn)采用 UTF8編碼格式編碼字符串,但并不將 UTF8所對(duì)應(yīng)的 BOM值(“ EF BB BF”)寫(xiě)入到二進(jìn)制流中。以下是 StreamWriter的一個(gè)構(gòu)造函數(shù)聲明:
       
public  StreamWriter( string  path) :  this (path,  false ,  UTF8NoBOM ,  0x400 )
{    }
         類(lèi)似地, File.ReadAllText()方法在內(nèi)部使用 UTF8來(lái)讀取指定文件中的字符串 :
public   static   string  ReadAllText( string  path)
{
     // ……
     return  InternalReadAllText(path, Encoding.UTF8);
}
     由于默認(rèn)編碼方式一致,所以配套使用 StreamWriter和 File.ReadAllText()方法可以正確地從流中存取字符串。
    出于提升代碼可維護(hù)性考慮,正確的用法應(yīng)該是明確地指明編碼方式:
 
static   void  WriteFileUseStreamWriterUseUTF8(String fileContent, String FileName)
{
     using  (StreamWriter writer  =   new  StreamWriter(FileName,  false ,  Encoding.UTF8 ))
    {
                   writer.Write(fileContent);
    }
}
          這時(shí), StreamWriter會(huì)在文件開(kāi)頭寫(xiě)入 UTF8的 BOM標(biāo)記,從而讓其他的應(yīng)用程序可以很明確地知道本文件中字符串的編碼方式。
4 談?wù)動(dòng)腥さ?Encoding.Default 屬性
        
         Encoding 類(lèi)中有一個(gè)有趣的 Default屬性,它的類(lèi)型很奇怪,叫作“ DBCSCodePageEncoding”,這個(gè)類(lèi)型在 MSDN中是查不到的。
         “ DBCS”代表“ double-byte character set (雙字節(jié)字符集)”,它是與“ SBCS( single-byte character set,單字節(jié)字符集)”相對(duì)應(yīng)的, SBCS中,所有字符都只占一個(gè)字節(jié),所以能表示的字符數(shù)有限,但在 DBCS中,英文字母占一個(gè)字節(jié),漢字等特殊字符占有兩個(gè)字節(jié),從而擴(kuò)充了 Windows能顯示的字符數(shù)量。
         DBCSCodePageEncoding 中的“ Code Page”被稱(chēng)為“ 代碼頁(yè) ”,每個(gè)代碼頁(yè)定義了特定的編碼將如何對(duì)應(yīng)于特定的字符(比如簡(jiǎn)體和繁體中文就分別定義在不同的代碼頁(yè)中),因此,同樣的二進(jìn)制數(shù)值,在不同的代碼頁(yè)中,會(huì)代表不同的字符。中文 Windows通過(guò)使用基于代碼頁(yè)的 DBCS編碼方式,可以方便地以多種編碼方式顯示和處理字符串。
         我們?cè)?MSDN中可以查到所有代碼頁(yè)的編號(hào),下面列出了可能比較常用的代碼頁(yè)標(biāo)識(shí):
代碼頁(yè)標(biāo)識(shí)值        .NET中的名字
--------------------------------------------------------------------------------
936                   gb2312
950                   big5
1200                 utf-16
52936               hz-gb-2312
54936               GB18030
65000               utf-7
65001               utf-8

         .NET 應(yīng)用程序可以通過(guò)以下方式獲取指定代碼頁(yè)的編碼對(duì)象:
        
Encoding encode = Encoding.GetEncoding(CodePage);
         以下代碼將按照指定代碼頁(yè)編碼字符串,并將其寫(xiě)入到文件中:
static   void  WriteFileUseStreamWriterUseCodePage(String fileContent,String FileName, int  CodePage)
{
   using  (StreamWriter writer  =   new  StreamWriter(FileName,  false , Encoding.GetEncoding(CodePage)))
   {
        writer.Write(fileContent);
   }
}
    現(xiàn)在,使用以下代碼將按照 UTF8編碼字符串:
WriteFileUseStreamWriterUseCodePage( " 中國(guó)ab " ,  " test.txt " ,  65001 );
5 結(jié)束語(yǔ)
         除了本文所介紹的將字符串保存到文本文件的這種場(chǎng)景,字符串的編碼方式在基于套接字的 TCP/UDP網(wǎng)絡(luò)編程也非常重要,比如 .NET提供了一個(gè) NetworkStream封裝 Socket實(shí)現(xiàn)網(wǎng)絡(luò)通訊,如果希望將一個(gè)命令字符串從客戶端送到服務(wù)端,服務(wù)端通過(guò)讀取這個(gè)字符串完成特定的工作,則編碼方式就很重要了,客戶端與服務(wù)端必須采用一致的編碼方式傳送命令,否則,網(wǎng)絡(luò)服務(wù)就有可能因?yàn)闊o(wú)法解析客戶端發(fā)送過(guò)來(lái)的數(shù)據(jù)而 Down掉。
         有關(guān)網(wǎng)絡(luò)編程的內(nèi)容很有趣,我的下一篇文章會(huì)介紹 .NET套接字編程。
         好了,這篇介紹字符串編碼的短文寫(xiě)完了,希望本文能對(duì)讀者有所幫助,如有錯(cuò)誤,敬請(qǐng)指正。

本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/bitfan/archive/2010/11/25/6035134.aspx
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C# 對(duì)文本文件的讀寫(xiě)
c#文件讀寫(xiě)相關(guān)類(lèi)介紹
字符編碼問(wèn)題摘要
學(xué)藝要精,思考要慎.--轉(zhuǎn)UTF-8編碼的啟發(fā)
Python字符編碼詳解
【轉(zhuǎn)】Vim 字符編碼轉(zhuǎn)換
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服