ANSI,ASCII,UNICODE
轉載:http://blog.csdn.net/zj510/article/details/38368397
一直以來,編碼問題都是比較令人糾結的,我自己也是,迷惑了好一段時間。
首先看一下ANSI編碼和ASCII 編碼,用google搜到這篇文章,挺好的。http://www.differencebetween.net/technology/web-applications/difference-between-ansi-and-ascii/
ASCII: American Standard Code for Information Interchange
ANSI: American National Standard Institute
基本的區別就是:
[plain] view plaincopyprint?然后又看到這篇文章,也不錯,http://blog.csdn.net/zj510/article/details/37877651。建議仔細閱讀。
這里,我主要再介紹一下ansi,unicode和utf8
首先看一下ANSI
ANSI編碼
首先在C++代碼里面敲入一行代碼,很簡單看下圖,運行一下,會發現字符串ansi里面的內存是0xb3, 0xcc, 0xd0, 0xf2, 0xd4, 0xb1.打開記事本,寫入“程序員”3個字,然后save,用ultraedit看一下十六進制編碼,如下圖。
跟VS里面看到的一模一樣。我們在看一下C++的源文件。
看16進制的源文件,可以發現源文件里面的“程序員”3個字也是ANSI編碼。好像VS對于C++源文件默認的就是ANSI編碼,我在VS2013里面看到有個功能可以自動檢測UTF-8編碼啥的。但是沒有仔細研究過。
OK, 現在我們知道,在notepad里面,打入一些字符,然后save,那么默認的就是ANSI編碼。在VS里面如果輸入一些常量字符串,假如是純英文的話,那應該也是ANSI編碼,如果你的常量字符串里面有中文或者韓文等其他字符的話,就視情況而定了,像vs2013可能會把你的源文件轉換成UTF8格式,但我知道早期的VS是不會轉的還是用ANSI.所以如果你在IDE,比如VS, Eclipse,甚至XCODE等里面輸入常量字符串的話,需要小心。通常如果只是英文的話,一般是沒有問題的,但是如果有中文的話,要留個心眼,看你的IDE是怎么編碼的。不然恐怕就會出現亂碼的情況。當然如果真的有中文等字符的話,也不建議使用ANSI編碼,盡可能使用UNICODE吧。
UNICODE
unicode其實有好幾種,比如unicode16,unicode32啥的。通常我們在寫程序的時候,說起unicode或者寬字符,一般指的就是unicode16.也就是2個字節(wchar_t)來表示一個字符。一個英文字母a使用2個字節的寬字節wchar_t來表示,一個中文也是用一個wchar_t來表示。
notepad的saveas里面有個功能,可以把當前文件保存成unicode。
同樣打開notepad輸入“程序員”3個字,然后點擊save as,在編碼那里選擇unicode。如圖
保存完之后,用ultraedit打開,前面兩個字節FFFE,這個其實是notepad的一個標記,不用管它,看后面的6個字節。“程序員”總共是3個中文字符,那么用unicode就是6個字節,也就是0B7A8F5E5854.
OK, 現在C++程序里面敲入一行代碼,如下圖.從下面的圖片里面可以看到unicode字符串的內存是0x7a0b, 0x5e8f, 0x5458.跟上面ultraedit里面比較。好像每兩個字節都反過來了,這是何故?
其實這里有個很好玩的事情。我們直接看unicode里面的指向的內存吧。
unicode指向的是地址0x0026fb90,看內存,內存里面的數據是0b, 7a, 8f, 5e, 58, 54。跟上面ultraedit里面顯示的是一致的。那么說明unicode里面在內存存放的字節流跟ultraedit里面展示的是一模一樣的。那為什么用wchar_t表示的時候就反過來了呢?其實我覺得這應該是windows上面的機制,用wchar_t表示的時候就是反過來的(不知道linux上是不是也是這樣?),就好象是int在內存里面存放也是逆序的。
順便再來看一下C#吧,寫幾行簡單代碼,直接看下圖:
首先我們可以看到sizeof(char)在C#里面是2.其實在C#里面并沒有wchar_t這種東西。只有一個char,而它就是2個字節。這是因為C#里面用的都是unicode。C#的string里面存放的就是unicode格式。好像Java也是這樣。每一個char和上面的C++的wchar_t的值一模一樣。
ANSI VS Unicode
那么我們到底應該使用ANSI還是Unicode呢?我建議使用Unicode,特殊是在寫windows程序的時候,因為windows的API都支持ANSI和Unicode兩種,也就是我們常說的多字節和寬字節。比如CreateFileA()支持ANSI編碼, CreateFileW()支持Unicode編碼。如果使用Ansi的話,萬一你的字符串里面含有中文,就會比較麻煩一些,比如有些時候為了換行,很難計算,以為ANSI里面英文占一個自己,中文占2個字節。如果把一個中文給劈開了,那就顯示亂碼了。如果使用Unicode就很方便了,因為中文,英文都是占2個字節。當然如果你的程序確定只支持英文,那用ANSI也行,畢竟用Unicode的話,會多占內存。假如一個英文字符串有100個字符,用ANSI就占用100字節,用UNICODE就是200字節。Windows的大多數API都支持ANSI和UNICODE兩種,我個人比較喜歡用UNICODE版本,畢竟現在的內存動不動都4g,8g的,多耗些內存也不是什么大問題。
utf8
最后再介紹一種非常常用的編碼utf8. 什么是utf-8, 看定義, UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters
至于utf8的具體細節和好處,網上一搜一大堆。基本上現在的網頁用的都是utf-8編碼,數據庫里面用的很多也是utf-8,網絡傳輸也是很多使用utf8。反正我覺得utf8的使用率是非常高的。比如我們想把一個字符串存入本地文件的時候也可以使用utf8編碼,當然也使用ANSI或者UNICODE. 這里就簡單介紹一下C++和Java里面的utf8使用吧。在C++里面,現在可以使用C++11了,簡單的一個例子,把一個unicode字符串轉換成utf8,再把utf8轉換成unicode
[cpp] view plaincopyprint?如果用C#就更簡單了。我們可以看到utf8編碼的字節流跟C++的一模一樣。
最后看一下c#源文件的編碼,我這里的c#源文件編碼用的是UNICODE, 看圖:(好像如果有中文的話,VS會轉換成utf8)
盡量不要在源代碼文件里面hardcode需要顯示在UI上的字符串
比如類似的代碼:
[cpp] view plaincopyprint?這個真的不是好習慣。如果你的程序要支持其他語言的話,你就不得不修改源文件而且重新編譯了。而且萬一需要支持中文的話,那么就得在字符串常量里面寫中文,可是有些時候又不知道源文件是用什么格式來編碼的。比如源文件是用utf8編碼的話,文件就來的,SetWindowText()是不支持utf8編碼顯示的,我們不得不先把utf8編碼轉換成ANSI或者UNICODE,再調用windows API。還有其他問題,比如你用VS UNICODE編碼來寫程序的,而另外一個人用Xcode來寫程序,那么你的中文在他的Xcode里面肯定顯示亂碼。總之很麻煩。我覺得我們的字符串常量應該盡可能放在資源文件里面,比如C++的resource文件,C#的資源文件。android程序也是有資源文件。這樣比較好,如果要改字符串的話,改資源文件就可以了。不需要跟源代碼。當然如果是一些log之類的字符串,寫在源代碼文件里面倒也問題不大,因為這些log通常都是英文,而且沒有localization的問題。
其他編碼
除了ANIS, UNICODE, UTF8之后還有很多其他的編碼,但是我覺得這三種是最常用的。而且一旦掌握了這三種以后,再看其他的編碼應該也是很容易了。
總結
以上是生活随笔為你收集整理的ANSI,ASCII,UNICODE的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 方式四:修改模块导入段来拦截API
- 下一篇: 进程权限