漢字區位碼查詢與算法——microsoft visual studio 2005系列

 要從事學術研究,一定要學好數學,數學可以把對事物的描述精確化。
tuenhai爲什麼要學習編程?其中一個原因就是利用編程工具進行一些數學運算。
記得大約10年前,那時tuenhai還沒有電腦,要進行大數計算,怎麼辦?那時就到處打聽,哪裏有數位多一些的計算器。一般計算器只有8位,多一些的12位,還是不夠用。有一次和故人到大城市,總算打聽到了超過12位的計算器,考慮再三,還是沒有買下來(不知故人還有沒有記得這件事,畢竟過去這麼多年了)。

父親把我們以前讀過的教材,練習本都保存着,我把粘滿灰塵的數學教材找出來,放在我的書房,有時還會去隨便翻翻。
現在學校教育是徹頭徹尾的失敗。教育沒有和實際結合,畢業不久,學過的知識就很多交還給老師了。想起來,學校教育至少浪費了我5年光陰,工作中又至少浪費了我8年光陰,從出生到現在,竟有近一半時間浪費掉了,實在可怕。

把學校教育批評得一無是處,那麼理想的教育應該是怎麼樣的呢?
理想的教育應該是一切學科相通的,只有這樣,知識才能活起來,學而即用,不用死記。這樣的學習,只有快樂,沒有痛苦。

這樣的學校教育可謂是完美,在這個不完美的世界可能永遠不會實現。就象中醫,這麼多人說要發揚真正的中醫,但現代人沒有這個福氣,連僞中醫都要衰落,何況真中醫。現代“小火神”爲什麼不寫書,或許有深機在焉。

一切學科相通,從而理解這個世界,這個題目太大了,tuenhai(tuenhai.com)也只是玩味了一點點。這裏只討論一下用編程的方法數字與漢字的轉換,同時也附錄一些資料,方便研究。

 

'tuenhai所用獲得漢字或字符對應的區位符
Function quwei(ByVal x As String) As String '
x = Asc(x) 'Asc 返回輸入字符的碼位或字符代碼。對於單字節字符集 (SBCS),返回值範圍爲 0 到 255;對於雙字節字符集 (DBCS),返回值範圍爲 -32768 到 32767。對於單字節 ASCII 字符的圖表,請參見 ASCII 字符代碼。
x = Hex((x)) '返回表示數字的十六進制值的字符串。劉=FFFFC1F5,前面的4個F去掉,得到16進制的內碼。16進制的C=10進制的12
Dim str As String
str = Format(CDec("&H" & Strings.Mid(x, 5, 2)) - 160, "00") & Format(CDec("&H" & Strings.Mid(x, 7, 2)) - 160, "00")
'Strings.Mid(x, 5, 2) '得到16進制的內碼,“劉”內碼高位=C1
'CDec("&H" & str) '轉換成10進制內碼,"&H"表示16進制 “劉”內碼高位=193
'-160 得到10進制區碼, “劉”區碼是33
'Format(decQu, "00") '格式化爲兩位數表示
Return str
End Function
'GB2312的原文還是區位碼,從區位碼到內碼,需要在高字節和低字節上分別加上A0,
'在DBCS中,GB內碼的存儲格式始終是big endian,即高位在前。
' 區位碼是與漢字一一對應的編碼,用四位數字表示, 前兩位從01 到94稱區碼,後兩位從01到94稱位碼。 一個漢字的前一半是 ASCⅡ碼爲“160+區碼”的字符,後一半是ASCⅡ碼爲“160+ 位碼”的字符。
'例如:“劉”的區位碼是 3385,其意爲區碼33位碼85,它是由ASCⅡ碼爲160+33=193和160+85=245的兩個字符組成。

 

 


'tuenhai所用獲得區位符對應漢字或字符
Function hanzi(ByVal x As String) As String '
On Error Resume Next
Dim str As String
str = Chr("&H" & Hex(Val(Strings.Left(x, 2)) + 160) & Hex(Val(Strings.Right(x, 2)) + 160))
Return (str)
End Function
'Chr 使用 System.Text 命名空間中的 Encoding 類來確定當前線程使用的是單字節字符集 (SBCS) 還是雙字節字符集 (DBCS)。然後將 CharCode 作爲相應字符集中的碼位。對於 SBCS 字符,範圍爲 0 到 255,對於 DBCS 字符,範圍爲 -32768 到 65535。
'ChrW 以 CharCode 作爲 Unicode 碼位。其範圍與當前線程的區域性和代碼頁設置無關。-32768 到 -1 範圍內的值的處理方式與 +32768 到 +65535 範圍內的值相同。

 

(更多文章請訪問www.tuenhai.com 20060427 剡)


<<<區位碼>>>

 

附錄:

 


從漢字到區位碼的轉換

http://blog.csdn.net/leeajax/archive/2004/07/12/39686.aspx
學校要我們填寫畢業生的情況表,機讀卡那種,姓名要用區位碼.我想如果用程序來查詢的話,就是數據庫查找,我想編一個應該很簡單的,就上網看看有沒有類似的程序,然後我再用它的數據庫自己實現一個,可讓我查到了一個文章講如何實現從漢字到區位碼的轉換,呵呵,可以不用數據庫了.
區位碼是與漢字一一對應的編碼,用四位數字表示, 前兩位從01 到94稱區碼,後兩位從01到94稱位碼。 一個漢字的前一半是 ASCⅡ碼爲“160+區碼”的字符,後一半是ASCⅡ碼爲“160+ 位碼”的字符。
例如:“劉”的區位碼是 3385,其意爲區碼33位碼85,它是由ASCⅡ碼爲160+33=193和160+85=245的兩個字符組成。

我用簡單的控制檯程序實現如下
#i nclude
#i nclude
void main()
{
char i[64];
while(1)
{
cout<<"輸入單個字母退出"< cin>>i;
if(strlen(i)==1)break;
for(int j=0;j cout<<(i[j]+96)*100+i[j+1]+96< }
}

 

 

 


如何隨機生成指定數目的國標漢字?


http://blog.csdn.net/northwolves/archive/2004/07/25/51270.aspx

爲了使每一個漢字有一個全國統一的代碼,1980年,我國頒佈了第一個漢字編碼的國家標準: GB2312-80《信息交換用漢字編碼字符集》基本集,這個字符集是我國中文信息處理技術的發展基礎,也是目前國內所有漢字系統的統一標準。由於國標碼是四位十六進制,爲了便於交流,大家常用的是四位十進制的區位碼。所有的國標漢字與符號組成一個94×94的矩陣。在此方陣中,每一行稱爲一個"區",每一列稱爲一個"位",因此,這個方陣實際上組成了一個有94個區(區號分別爲0 1到94)、每個區內有94個位(位號分別爲01到94)的漢字字符集。一個漢字所在的區號和位號簡單地組合在一起就構成了該漢字的"區位碼"。在漢字的區位碼中,高兩位爲區號,低兩位爲位號。 在區位碼中,01-09區爲682個特殊字符,16~87區爲漢字區,包含6763個漢字 。其中16-55區爲一級漢字(3755個最常用的漢字,按拼音字母的次序排列),56-87區爲二級漢字(3008個漢字,按部首次序排列)。

所以,當我們需要n個任意漢字時,我們不必建一個全部漢字表,而是利用區位碼實現常用漢字的提取。

下面的代碼可以實現任意數目漢字的生成:

Private Sub getrndhanzi(ByVal n As Integer)
Dim s() As String, i As Integer
Dim temp1 As Integer, temp2 As Integer
ReDim s(1 To n)
Randomize
For i = 1 To n
temp1 = 16 + Int(Rnd * 72)
If temp1 = 55 Then
temp2 = Int(Rnd * 90) '一級漢字從1601-1694,1701-1794,.....5401-5494,5501-5589,共94*40-5=3755 個漢字
Else
temp2 = Int(Rnd * 95) '二級漢字從5601-5694,5701-5794,.....8601-8694,8701-8794,共94*32=3008 個漢字
End If
s(i) = Chr("&H" & Hex(temp1 + 160) & Hex(temp2 + 160))
Next
Debug.Print Join(s, "")'輸出
End Sub

Private Sub Command1_Click()
Dim i As Integer
For i = 1 To 25 '分別生成1-25個任意漢字
getrndhanzi i
Next
End Sub

輸出:


夫敞
途罨椽
涅搦侄鋱
榨藸禒艟球
枵舟斟盯灘桫
猻暗田苫撂蕾岢
冠澧炫鱝噘惺馘柘
巧愁炔嗶臆策秈錠昏
紶假媼慈乘嘎膚景濡薤
呋刨鍾灰櫸懋脣弱獻囟垤
均耋撤闐驛邇愍殞堝砸宕薅
蒹翦俄形碌哧烀爝懶繚嬪捭渾
瑾碸癧嚌遒濂勾彐綘珩苓就萌炳
光槨旖趁鯤頎壕狁媼暑額愾帷淤黹
湫薰褲降旺廓淳傻蛻脬蓀色注紫劾吾
陶瀝瑗骶埴於喃刮癭突賅斛簡銓觴抨唼
格鴿乜衍夙菀鱺敗陸褐噲苑滓淆踵訖頭綁
德泠婷嶴湔池槳郅峁汩卒控訴芻鏜椎鬣越嫉
義懂聶其定鰳脯膪巰吐昏罰返抖陵沌戧喘茺緙
廢霧旯浠疼贓勳妓鱒埏幫盂蕹朐裂祆羶拌脎威純
宛免作繡稞涑梟搬懌旦熨呈棄馳翔聚飾栩燧艴氫貧
豕源髑乍蚍夏己履畢芤毀簣子褊崖壞忑黴鈿瘢駔遷裨
獬紛胚槳衫蹣瘋祧武琢唚酃踱免逘濁頇坐磬挫鄶嬸繆錳
拽技薯帙陝槲逗蜱嘧雌怙詿橢踉盔鋶認致暝榴櫱逆捻蟎噬

附:

漢字與區位碼轉換代碼:

Function quwei(ByVal x As String) As String '獲得某漢字或字符對應的的區位碼
If Asc(x) >= 0 Then Exit Function
x = Hex(Asc(x))
quwei = Format(CDec("&H" & Left(x, 2)) - 160, "00") & Format(CDec("&H" & Right(x, 2)) - 160, "00")
End Function


Function hanzi(ByVal x As String) As String'獲得某區位碼對應漢字或字符
hanzi = Chr("&H" & Hex(Val(Left(x, 2)) + 160) & Hex(Val(Right(x, 2)) + 160))
End Function

 

 

 


經驗總結--字符串與編碼

 

http://www.cnblogs.com/hellosnoopy/articles/98127.html

Posted on 2005-01-27 12:17 HelloSnoopy開發田地 閱讀(229) 評論(0) 編輯 收藏 收藏至365Key
SRC:http://search.csdn.net/Expert/topic/1880/1880675.xml?temp=3.344363E-02
這幾個月作手機短信的項目,碰到了很多字符編碼的問題,真頭痛。經過多番資料的搜索、親手嘗試和高人的指點,現在好像沒那麼迷惘了。現作了一些總結跟大家分享(有誤之處請指點)

首先應該把字節數組看成是String的載體。
dot Net使用的字符串String是Unicode編碼的;它也是以Unicode編碼的形式顯示字符串。

以下是用自己語言對幾個常用函數的說明:
(自己總結的,反正看不明MSDN)
bytes=System.Text.Encoding.Unicode.GetBytes(str)
作用:把str的載體作Unicode->Unicode的編碼轉換--也就是沒有對載體作任何的轉換。因些使用此函數可以得代表該String載體的字節數組。
str=System.Text.Encoding.Unicode.GetString(bytes)
作用:對字節數組作Unicode->Unicode的編碼轉換--即沒有轉換,把經過轉換後的字節數組作爲str的載體。

bytes=System.Text.Encoding.Utf8.GetBytes(str)
作用:把str的載體作Utf8->Unicode的編碼轉換。返回的是經過轉換後的字符數組
str=System.Text.Encoding.Utf8.GetString(bytes)
作用:對字節數組作Gb2312->Unicode的編碼轉換,把經過轉換後的字節數組作爲str的載體。

bytes=System.Text.Encoding.GetEncoding("GB2312").GetBytes(str)
作用:把str的載體作Gb2312->Unicode的編碼轉換。返回的是經過轉換後的字符數組
str=System.Text.Encoding.GetEncoding("GB2312").GetString(bytes)
作用:對字節數組作Gb2312->Unicode的編碼轉換,把經過轉換後的字節數組作爲str的載體。

如此類推
bytes=System.Text.Encoding.GetEncoding("XXX").GetBytes(str)
作用:把str的載體作XXX->Unicode的編碼轉換。返回的是經過轉換後的字符數組
str=System.Text.Encoding.GetEncoding("XXX").GetString(bytes)
作用:對字節數組作XXX->Unicode的編碼轉換,把經過轉換後的字節數組作爲str的載體。

這裏是我收集的一些有關字符編碼的資料:http://61.145.116.154/bm/
還有:
http://www.unicode.org/charts/unihan.html
根據Unicode編碼查其對應字符的字形、Utf8、漢字區位碼等
http://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/GB/GB2312.TXT Unicode與Gb2312的對照表
http://www.sun.com/developers/gadc/technicalpublications/articles/mabiao.txt
Unicode與Gbk對照表

 

 

 

 


用C#生成中文漢字驗證碼的基本原理


http://dev.csdn.net/develop/article/67/67031.shtm

前幾天去申請免費QQ號碼,突然發現申請表單中的驗證碼內容換成了中文,這叫真叫我大跌眼鏡感到好笑,Moper上的貓兒們都大罵騰訊採用中文驗證碼。^_^
我不得不佩服騰訊爲了防止目前網絡上橫行的QQ號碼自動註冊機而採取中文驗證碼的手段。仔細想了想感覺用程序生成隨機的中文驗證碼並不是很難,下面就來介紹一下使用C#生成隨機的中文漢字的原理。


1、漢字編碼原理
到底怎麼辦到隨機生成漢字的呢?漢字從哪裏來的呢?是不是有個後臺數據表,其中存放了所需要的所有漢字,使用程序隨機取出幾個漢字組合就行了呢?使用後臺數據庫先將所有漢字存起來使用時隨機取出,這也是一種辦法,但是中文漢字有這麼多,怎麼來製作呢?其實可以不使用任何後臺數據庫,使用程序就能做到這一切。要知道如何生成漢字,就得先了解中文漢字的編碼原理。
1980年,爲了使每一個漢字有一個全國統一的代碼,我國頒佈了第一個漢字編碼的國家標準: GB2312-80《信息交換用漢字編碼字符集》基本集,簡稱GB2312,這個字符集是我國中文信息處理技術的發展基礎,也是國內所有漢字系統的統一標準。到了後來又公佈了國家標準GB18030-2000《信息交換用漢字編碼字符集基本集的擴充》,簡稱GB18030,編程時如果涉及到編碼和本地化的朋友應該對GB18030很熟悉。這是是我國繼GB2312-1980和GB13000-1993之後最重要的漢字編碼標準,同時也是未來我國計算機系統必須遵循的基礎性標準之一。
目前在中文WINDOWS操作系統中,.NET編程中默認的的代碼頁就是GB18030簡體中文。但是事實上如果生成中文漢字驗證碼只須要使用GB2312字符集就已經足夠了。字符集中除了我們平時大家都認識的漢字外,也包含了很多我們不認識平時也很少見到的漢字。如果生成中文漢字驗證碼中有很多我們不認識的漢字讓我們輸入,對於使用拼音輸入法的朋友來說可不是好事,五筆使用者還能勉強根據漢字的長相打出來,呵呵!所以對於GB2312字符集中的漢字我們也不是全都要用。
中文漢字字符可以使用區位碼來表示,見

漢字區位碼錶 http://navicy2005.home4u.china.com/resource/gb2312tbl.htm
漢字區位碼代碼表 http://navicy2005.home4u.china.com/resource/gb2312tbm.htm

其實這兩個表是同一回事,只不過一個使用十六進制分區表示,一個使用區位所在的數字位置表示。 例如“好”字的十六進制區位碼是ba c3,前兩位是區域,後兩位代表位置,ba處在第26區,“好”處在此區漢字的第35位也就是c3位置,所以數字代碼就是2635。這就是GB2312漢字區位原理。根據《漢字區位碼錶 》我們可以發現第15區也就是AF區以前都沒有漢字,只有少量符號,漢字都從第16區B0開始,這就是爲什麼GB2312字符集都是從16區開始的。

2、.Net程序處理漢字編碼原理分析
在.Net中可以使用System.Text來處理所有語言的編碼。在System.Text命名空間中包含衆多編碼的類,可供進行操作及轉換。其中的Encoding類就是重點處理漢字編碼的類。通過在.NET文檔中查詢Encoding類的方法我們可以發現所有和文字編碼有關的都是字節數組,其中有兩個很好用的方法:


Encoding.GetBytes ()方法將指定的 String 或字符數組的全部或部分內容編碼爲字節數組
Encoding.GetString ()方法將指定字節數組解碼爲字符串。

沒錯我們可以通過這兩個方法將漢字字符編碼爲字節數組,同樣知道了漢字GB2312的字節數組編碼也就可以將字節數組解碼爲漢字字符。通過對“好”字進行編碼爲字節數組後


Encoding gb=System.Text.Encoding.GetEncoding("gb2312");
object[] bytes=gb.Encoding.GetBytes ("好");

發現得到了一個長度爲2的字節數組bytes,使用


string lowCode = System.Convert.ToString(bytes[0], 16); //取出元素1編碼內容(兩位16進制)
string hightCode = System.Convert.ToString(bytes[1], 16);//取出元素2編碼內容(兩位16進制)

之後發現字節數組bytes16進制變碼後內容竟然是{ba,c3},剛好是“好”字的十六進制區位碼(見區位碼錶)。
因此我們就可以隨機生成一個長度爲2的十六進制字節數組,使用GetString ()方法對其進行解碼就可以得到漢字字符了。不過對於生成中文漢字驗證碼來說,因爲第15區也就是AF區以前都沒有漢字,只有少量符號,漢字都從第16區B0開始,並且從區位D7開始以後的漢字都是和很難見到的繁雜漢字,所以這些都要排出掉。所以隨機生成的漢字十六進制區位碼第1位範圍在B、C、D之間,如果第1位是D的話,第2位區位碼就不能是7以後的十六進制數。在來看看區位碼錶發現每區的第一個位置和最後一個位置都是空的,沒有漢字,因此隨機生成的區位碼第3位如果是A的話,第4位就不能是0;第3位如果是F的話,第4位就不能是F。
好了,知道了原理,隨機生成中文漢字的程序也就出來了,以下就是生成4個隨機漢字的C#控制檯代碼:


3、程序代碼:

 

using System;
using System.Text;

namespace ConsoleApplication
{
class ChineseCode
  {
public static void Main()
{
//獲取GB2312編碼頁(表)
Encoding gb=Encoding.GetEncoding("gb2312");

//調用函數產生4個隨機中文漢字編碼
object[] bytes=CreateRegionCode(4);

//根據漢字編碼的字節數組解碼出中文漢字
string str1=gb.GetString((byte[])Convert.ChangeType(bytes[0], typeof(byte[])));
string str2=gb.GetString((byte[])Convert.ChangeType(bytes[1], typeof(byte[])));
string str3=gb.GetString((byte[])Convert.ChangeType(bytes[2], typeof(byte[])));
string str4=gb.GetString((byte[])Convert.ChangeType(bytes[3], typeof(byte[])));

//輸出的控制檯
   Console.WriteLine(str1 + str2 +str3 +str4);
   }


/**//*
此函數在漢字編碼範圍內隨機創建含兩個元素的十六進制字節數組,每個字節數組代表一個漢字,並將
四個字節數組存儲在object數組中。
參數:strlength,代表需要產生的漢字個數
*/
public static object[] CreateRegionCode(int strlength)
{
//定義一個字符串數組儲存漢字編碼的組成元素
string[] rBase=new String [16]{"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};

Random rnd=new Random();

//定義一個object數組用來
object[] bytes=new object[strlength];

/**//*每循環一次產生一個含兩個元素的十六進制字節數組,並將其放入bject數組中
每個漢字有四個區位碼組成
區位碼第1位和區位碼第2位作爲字節數組第一個元素
區位碼第3位和區位碼第4位作爲字節數組第二個元素
*/
for(int i=0;i {
//區位碼第1位
int r1=rnd.Next(11,14);
string str_r1=rBase[r1].Trim();

//區位碼第2位
rnd=new Random(r1*unchecked((int)DateTime.Now.Ticks)+i);//更換隨機數發生器的

種子避免產生重複值
int r2;
if (r1==13)
{
r2=rnd.Next(0,7);
}
else
{
r2=rnd.Next(0,16);
}
string str_r2=rBase[r2].Trim();

//區位碼第3位
rnd=new Random(r2*unchecked((int)DateTime.Now.Ticks)+i);
int r3=rnd.Next(10,16);
string str_r3=rBase[r3].Trim();

//區位碼第4位
rnd=new Random(r3*unchecked((int)DateTime.Now.Ticks)+i);
int r4;
if (r3==10)
{
r4=rnd.Next(1,16);
}
else if (r3==15)
{
r4=rnd.Next(0,15);
}
else
{
r4=rnd.Next(0,16);
}
string str_r4=rBase[r4].Trim();

//定義兩個字節變量存儲產生的隨機漢字區位碼
byte byte1=Convert.ToByte(str_r1 + str_r2,16);
byte byte2=Convert.ToByte(str_r3 + str_r4,16);
//將兩個字節變量存儲在字節數組中
byte[] str_r=new byte[]{byte1,byte2};

//將產生的一個漢字的字節數組放入object數組中
bytes.SetValue(str_r,i);

}

return bytes;

}
  }

}


實現了隨機生成漢字後,就可以使用.NET GDI來繪製自己需要的驗證碼圖形了。具體的怎樣生成驗證碼圖片,以及改變其中字符的長和寬等效果網上已經有很多相關的文章,這裏由於篇幅就不再介紹了。不過有一點要說明的是以上代碼在中文版的Windows下才能運行,因爲它帶有GB的字符集,如果你是其他語言的操作系統,就需要安裝GB字符集了。

有什麼問題可以到 http://www.cnblogs.com/navicy/ 發表看法。
http://navicy.126.com

 

 

 

 

用.NET獲取漢字的區位碼(C#)


http://dev.csdn.net/article/58/58359.shtm

首先複習一下計算機基礎知識:

  計算機中最底層的數據都是用二進制及0和1來表示的。每個0或1稱作1位,第8位二進制數叫做1個字節,它可以表示ASCII碼中的一個字符。中文計算機中用兩個字節即16位二進制來表示一個漢字。而在Unicode編碼中所有的符號(包括漢字,英文,標題及其它衆多符號)都是爲兩字節(16)位來表示。

  在System.Text命名空間中包含衆多編碼的類,可供進行操作及轉換,下面用兩個實例來進行區位碼及漢字之間的互換,希望能起到舉一反三的效果,讓大家可以輕鬆處理文字編碼方面的問題:

程序代碼:

  using System;
  using System.Text;
  class CodingChange
  {
  public string CharacterToCoding(string character)
  {
  string coding = "";
  for (int i = 0; i  {
  byte[] bytes = System.Text.Encoding.Unicode.GetBytes(character.Substring(i,1)); //取出二進制編碼內容
  string lowCode = System.Convert.ToString(bytes[0], 16); //取出低字節編碼內容(兩位16進制)
  if (lowCode.Length == 1)
  lowCode = "0" + lowCode;
  string hightCode = System.Convert.ToString(bytes[1], 16);//取出高字節編碼內容(兩位16進制)
  if (hightCode.Length == 1)
  hightCode = "0" + hightCode;
  coding += (lowCode + hightCode);//加入到字符串中,
  }
  return coding;
  }
  public string CodingToCharacter(string coding)
  {
  string characters = "";

轉自:http://www.guoblog.com/blogview.asp?logID=201

作者Blog:http://blog.csdn.net/AppleBBS/

 

 

 

 

 


2進制、8進制、10進制、16進制...各種進制間的輕鬆轉換(c#)


http://blog.csdn.net/gztoby/archive/2004/08/16/76293.aspx

在.NET Framework中,System.Convert類中提供了較爲全面的各種類型、數值之間的轉換功能。其中的兩個方法可以輕鬆的實現各種進制的數值間的轉換:

Convert.ToInt32(string value, int fromBase):

可以把不同進制數值的字符串轉換爲數字,其中fromBase參數爲進制的格式,只能是2、8、10及16:

如Convert.ToInt32(”0010”,2)執行的結果爲2;

Convert.ToString(int value, int toBase):

可以把一個數字轉換爲不同進制數值的字符串格式,其中toBase參數爲進制的格式,只能是2、8、10及16:

如Convert.ToString(2,2)執行的結果爲”0010”

現在我們做一個方法實現各種進制間的字符串自由轉換:選把它轉成數值型,然後再轉成相應的進制的字符串:

public string ConvertString(string value, int fromBase, int toBase)

{

int intValue = Convert.ToInt32(value, fromBase);

return Convert.ToString(intValue, toBase);
}

其中fromBase爲原來的格式

toBase爲將要轉換成的格式

yolle [原作]

 

 

 

進制轉換

http://www.ypdoor.com/blog/article.asp?id=76
電腦上的常用進制有:2、8、10、16四種,在修改中經常接觸的是2、10和16進制,基本上需要了解的是2和16互轉、10和16互轉,其他多瞭解也沒虧

2轉16:

4個2進制位爲一個16進制數,2進制1111爲16進制F,2進制中千位的1=8,百位的1=4,十位的1=2,個位的1=1,將各個位的數作相應轉換再相加,的到的數就是10進制數0-15,可輕鬆轉換成16進制。如01011100,可看成是兩組2進制數0101和1100,則這個數就是16進制的5C。

10轉16:

100以內一點的10轉16心算比較快,複雜的用“計算器”算了。10轉16用傳統的計算方式可以了,就是大於15小於256的10進制數除以16爲的值爲十位的16進制數,其餘數爲個位的16進制數,沒餘數則個位爲0。如61的16進制是3D,61除以16得3餘13,3作十位數,13轉成D爲各位數。
16轉10:
用相反的道理,將十位數乘以16加上個位數。如5A,將5乘以16得80,加上A的10進制10,結果是90。
最直接方便的方法是用windows或win95中的計算器,打開計算器,將計算器置成科學型(win95的乘法),選中十進制選擇鈕,輸入十進制數然後選擇二進制選擇鈕,OK!又快又準確。可是如果你想成爲一個合格的程序員的話,你就必須充分了解十進制數和二進制數的特點,最好的方法是你多做一些進制轉換的題目,這是程序員訓練中的傳統做法。
三、以十六進制作橋樑
十進制到二進制的轉換實在麻煩,而且二進制數實在不易記憶和理解,你能馬上感覺到一萬元是多少錢,但是你能感覺到10011100010000(二進制)是多少嗎?爲了編程和使用方便,在二進制和十進制之間有了一座橋樑十六進制。十六進制是逢十六進一,0、1、2、3、4、5、…9、A、B、C、D、E、F、10、11、12……。到了9以後用ABCDEF表示,十六進制數與二進制數的轉換非常方便。
首先你應當牢記下表
二進制 十六進制
0 0
1 1
10 2
11 3
100 4
101 5
110 6
111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F
二進制數轉換成十六進制數方法如下,以二進制數1101110爲例:
將二進制數從右面開始以四位爲一組分組,最左面不夠四位的補0,按上表查得對應的十六進制數,組合起來以後就成了。
0110 1110的十六進制數是6E
十六進制轉換成二進制方法如下,以十六進制數3E爲例:
將十六進制的每一位轉換成四位二進制數,不足四位的在左面補0,組合起來即可得到二進制數。
3E的二進制數是00111110,既是111110
當然你也可以用計算器得出結果。但也建議你熟練掌握。

 

 

Unicode簡介

http://www.1cn.biz/java/index.php?q=node/79
關鍵詞: 字庫,unicode,big5

Unicode是一種字符編碼規範 。

先從ASCII說起。ASCII是用來表示英文字符的一種編碼規範,每個ASCII字符佔用1個字節(8bits)

因此,ASCII編碼可以表示的最大字符數是256,其實英文字符並沒有那麼多,一般只用前128個(最高位爲0),其中包括了控制字符、數字、大小寫字母和其他一些符號 。

而最高位爲1的另128個字符被成爲“擴展ASCII”,一般用來存放英文的製表符、部分音標字符等等的一些其他符號

這種字符編碼規範顯然用來處理英文沒有什麼問題 。(實際上也可以用來處理法文、德文等一些其他的西歐字符,但是不能和英文通用),但是面對中文、阿拉伯文之類複雜的文字,255個字符顯然不夠用

於是,各個國家紛紛制定了自己的文字編碼規範,其中中文的文字編碼規範叫做“GB2312-80”,它是和ASCII兼容的一種編碼規範,其實就是利用擴展ASCII沒有真正標準化這一點,把一箇中文字符用兩個擴展ASCII字符來表示。

但是這個方法有問題,最大的問題就是,中文文字沒有真正屬於自己的編碼,因爲擴展ASCII碼雖然沒有真正的標準化,但是PC裏的ASCII碼還是有一個事實標準的(存放着英文製表符),所以很多軟件利用這些符號來畫表格。這樣的軟件用到中文系統中,這些表格符就會被誤認作中文字,破壞版面。而且,統計中英文混合字符串中的字數,也是比較複雜的,我們必須判斷一個ASCII碼是否擴展,以及它的下一個ASCII是否擴展,然後才“猜”那可能是一箇中文字 。

總之當時處理中文是很痛苦的。而更痛苦的是GB2312是國家標準,臺灣當時有一個Big5編碼標準,很多編碼和GB是相同的,所以……,嘿嘿。

這時候,我們就知道,要真正解決中文問題,不能從擴展ASCII的角度入手,也不能僅靠中國一家來解決。而必須有一個全新的編碼系統,這個系統要可以將中文、英文、法文、德文……等等所有的文字統一起來考慮,爲每個文字都分配一個單獨的編碼,這樣纔不會有上面那種現象出現。

於是,Unicode誕生了。

Unicode有兩套標準,一套叫UCS-2(Unicode-16),用2個字節爲字符編碼,另一套叫UCS-4(Unicode-32),用4個字節爲字符編碼。

以目前常用的UCS-2爲例,它可以表示的字符數爲2^16=65535,基本上可以容納所有的歐美字符和絕大部分的亞洲字符 。

UTF-8的問題後面會提到 。

在Unicode裏,所有的字符被一視同仁。漢字不再使用“兩個擴展ASCII”,而是使用“1個Unicode”,注意,現在的漢字是“一個字符”了,於是,拆字、統計字數這些問題也就自然而然的解決了 。

但是,這個世界不是理想的,不可能在一夜之間所有的系統都使用Unicode來處理字符,所以Unicode在誕生之日,就必須考慮一個嚴峻的問題:和ASCII字符集之間的不兼容問題。

我們知道,ASCII字符是單個字節的,比如“A”的ASCII是65。而Unicode是雙字節的,比如“A”的Unicode是0065,這就造成了一個非常大的問題:以前處理ASCII的那套機制不能被用來處理Unicode了 。

另一個更加嚴重的問題是,C語言使用'/0'作爲字符串結尾,而Unicode裏恰恰有很多字符都有一個字節爲0,這樣一來,C語言的字符串函數將無法正常處理Unicode,除非把世界上所有用C寫的程序以及他們所用的函數庫全部換掉 。

於是,比Unicode更偉大的東東誕生了,之所以說它更偉大是因爲它讓Unicode不再存在於紙上,而是真實的存在於我們大家的電腦中。那就是:UTF 。

UTF= UCS Transformation Format UCS轉換格式

它是將Unicode編碼規則和計算機的實際編碼對應起來的一個規則。現在流行的UTF有2種:UTF-8和UTF-16 。

其中UTF-16和上面提到的Unicode本身的編碼規範是一致的,這裏不多說了。而UTF-8不同,它定義了一種“區間規則”,這種規則可以和ASCII編碼保持最大程度的兼容 。

UTF-8有點類似於Haffman編碼,它將Unicode編碼爲00000000-0000007F的字符,用單個字節來表示;

00000080-000007FF的字符用兩個字節表示

00000800-0000FFFF的字符用3字節表示

因爲目前爲止Unicode-16規範沒有指定FFFF以上的字符,所以UTF-8最多是使用3個字節來表示一個字符。但理論上來說,UTF-8最多需要用6字節表示一個字符。

在UTF-8裏,英文字符仍然跟ASCII編碼一樣,因此原先的函數庫可以繼續使用。而中文的編碼範圍是在0080-07FF之間,因此是2個字節表示(但這兩個字節和GB編碼的兩個字節是不同的),用專門的Unicode處理類可以對UTF編碼進行處理。

下面說說中文的問題。

由於歷史的原因,在Unicode之前,一共存在過3套中文編碼標準。

GB2312-80,是中國大陸使用的國家標準,其中一共編碼了6763個常用簡體漢字。Big5,是臺灣使用的編碼標準,編碼了臺灣使用的繁體漢字,大概有8千多個。HKSCS,是中國香港使用的編碼標準,字體也是繁體,但跟Big5有所不同。

這3套編碼標準都採用了兩個擴展ASCII的方法,因此,幾套編碼互不兼容,而且編碼區間也各有不同

因爲其不兼容性,在同一個系統中同時顯示GB和Big5基本上是不可能的。當時的南極星、RichWin等等軟件,在自動識別中文編碼、自動顯示正確編碼方面都做了很多努力 。

他們用了怎樣的技術我就不得而知了,我知道好像南極星曾經以同屏顯示繁簡中文爲賣點。

後來,由於各方面的原因,國際上又制定了針對中文的統一字符集GBK和GB18030,其中GBK已經在Windows、Linux等多種操作系統中被實現。

GBK兼容GB2312,並增加了大量不常用漢字,還加入了幾乎所有的Big5中的繁體漢字。但是GBK中的繁體漢字和Big5中的幾乎不兼容。

GB18030相當於是GBK的超集,比GBK包含的字符更多。據我所知目前還沒有操作系統直接支持GB18030。


談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞
這是一篇程序員寫給程序員的趣味讀物。所謂趣味是指可以比較輕鬆地瞭解一些原來不清楚的概念,增進知識,類似於打RPG遊戲的升級。整理這篇文章的動機是兩個問題:

問題一:
使用Windows記事本的“另存爲”,可以在GBK、Unicode、Unicode big endian和UTF-8這幾種編碼方式間相互轉換。同樣是txt文件,Windows是怎樣識別編碼方式的呢?

我很早前就發現Unicode、Unicode big endian和UTF-8編碼的txt文件的開頭會多出幾個字節,分別是FF、FE(Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)。但這些標記是基於什麼標準呢?

問題二:
最近在網上看到一個ConvertUTF.c,實現了UTF-32、UTF-16和UTF-8這三種編碼方式的相互轉換。對於Unicode(UCS2)、GBK、UTF-8這些編碼方式,我原來就瞭解。但這個程序讓我有些糊塗,想不起來UTF-16和UCS2有什麼關係。
查了查相關資料,總算將這些問題弄清楚了,順帶也瞭解了一些Unicode的細節。寫成一篇文章,送給有過類似疑問的朋友。本文在寫作時儘量做到通俗易懂,但要求讀者知道什麼是字節,什麼是十六進制。

0、big endian和little endian
big endian和little endian是CPU處理多字節數的不同方式。例如“漢”字的Unicode編碼是6C49。那麼寫到文件裏時,究竟是將6C寫在前面,還是將49寫在前面?如果將6C寫在前面,就是big endian。還是將49寫在前面,就是little endian。

“endian”這個詞出自《格列佛遊記》。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開,由此曾發生過六次叛亂,其中一個皇帝送了命,另一個丟了王位。

我們一般將endian翻譯成“字節序”,將big endian和little endian稱作“大尾”和“小尾”。

1、字符編碼、內碼,順帶介紹漢字編碼
字符必須編碼後才能被計算機處理。計算機使用的缺省編碼方式就是計算機的內碼。早期的計算機使用7位的ASCII編碼,爲了處理漢字,程序員設計了用於簡體中文的GB2312和用於繁體中文的big5。

GB2312(1980年)一共收錄了7445個字符,包括6763個漢字和682個其它符號。漢字區的內碼範圍高字節從B0-F7,低字節從A1-FE,佔用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。

GB2312支持的漢字太少。1995年的漢字擴展規範GBK1.0收錄了21886個符號,它分爲漢字區和圖形符號區。漢字區包括21003個字符。2000年的GB18030是取代GBK1.0的正式國家標準。該標準收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。現在的PC平臺必須支持GB18030,對嵌入式產品暫不作要求。所以手機、MP3一般只支持GB2312。

從ASCII、GB2312、GBK到GB18030,這些編碼方法是向下兼容的,即同一個字符在這些方案中總是有相同的編碼,後面的標準支持更多的字符。在這些編碼中,英文和中文可以統一地處理。區分中文編碼的方法是高字節的最高位不爲0。按照程序員的稱呼,GB2312、GBK到GB18030都屬於雙字節字符集 (DBCS)。

有的中文Windows的缺省內碼還是GBK,可以通過GB18030升級包升級到GB18030。不過GB18030相對GBK增加的字符,普通人是很難用到的,通常我們還是用GBK指代中文Windows內碼。

這裏還有一些細節:

GB2312的原文還是區位碼,從區位碼到內碼,需要在高字節和低字節上分別加上A0。

在DBCS中,GB內碼的存儲格式始終是big endian,即高位在前。

GB2312的兩個字節的最高位都是1。但符合這個條件的碼位只有128*128=16384個。所以GBK和GB18030的低字節最高位都可能不是1。不過這不影響DBCS字符流的解析:在讀取DBCS字符流時,只要遇到高位爲1的字節,就可以將下兩個字節作爲一個雙字節編碼,而不用管低字節的高位是什麼。

2、Unicode、UCS和UTF
前面提到從ASCII、GB2312、GBK到GB18030的編碼方法是向下兼容的。而Unicode只與ASCII兼容(更準確地說,是與ISO-8859-1兼容),與GB碼不兼容。例如“漢”字的Unicode編碼是6C49,而GB碼是BABA。

Unicode也是一種字符編碼方法,不過它是由國際組織設計,可以容納全世界所有語言文字的編碼方案。Unicode的學名是"Universal Multiple-Octet Coded Character Set",簡稱爲UCS。UCS可以看作是"Unicode Character Set"的縮寫。

根據維基百科全書(http://zh.wikipedia.org/wiki/)的記載:歷史上存在兩個試圖獨立設計Unicode的組織,即國際標準化組織(ISO)和一個軟件製造商的協會(unicode.org)。ISO開發了ISO 10646項目,Unicode協會開發了Unicode項目。

在1991年前後,雙方都認識到世界不需要兩個不兼容的字符集。於是它們開始合併雙方的工作成果,併爲創立一個單一編碼表而協同工作。從Unicode2.0開始,Unicode項目採用了與ISO 10646-1相同的字庫和字碼。

目前兩個項目仍都存在,並獨立地公佈各自的標準。Unicode協會現在的最新版本是2005年的Unicode 4.1.0。ISO的最新標準是10646-3:2003。

UCS規定了怎麼用多個字節表示各種文字。怎樣傳輸這些編碼,是由UTF(UCS Transformation Format)規範規定的,常見的UTF規範包括UTF-8、UTF-7、UTF-16。

IETF的RFC2781和RFC3629以RFC的一貫風格,清晰、明快又不失嚴謹地描述了UTF-16和UTF-8的編碼方法。我總是記不得IETF是Internet Engineering Task Force的縮寫。但IETF負責維護的RFC是Internet上一切規範的基礎。

3、UCS-2、UCS-4、BMP

UCS有兩種格式:UCS-2和UCS-4。顧名思義,UCS-2就是用兩個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須爲0)編碼。下面讓我們做一些簡單的數學遊戲:

UCS-2有2^16=65536個碼位,UCS-4有2^31=2147483648個碼位。

UCS-4根據最高位爲0的最高字節分成2^7=128個group。每個group再根據次高字節分爲256個plane。每個plane根據第3個字節分爲256行 (rows),每行包含256個cells。當然同一行的cells只是最後一個字節不同,其餘都相同。

group 0的plane 0被稱作Basic Multilingual Plane, 即BMP。或者說UCS-4中,高兩個字節爲0的碼位被稱作BMP。

將UCS-4的BMP去掉前面的兩個零字節就得到了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就得到了UCS-4的BMP。而目前的UCS-4規範中還沒有任何字符被分配在BMP之外。

4、UTF編碼

UTF-8就是以8位爲單元對UCS進行編碼。從UCS-2到UTF-8的編碼方式如下:

UCS-2編碼(16進制) UTF-8 字節流(二進制)
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx

例如“漢”字的Unicode編碼是6C49。6C49在0800-FFFF之間,所以肯定要用3字節模板了:1110xxxx 10xxxxxx 10xxxxxx。將6C49寫成二進制是:0110 110001 001001, 用這個比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

讀者可以用記事本測試一下我們的編碼是否正確。

UTF-16以16位爲單元對UCS進行編碼。對於小於0x10000的UCS碼,UTF-16編碼就等於UCS碼對應的16位無符號整數。對於不小於0x10000的UCS碼,定義了一個算法。不過由於實際使用的UCS2,或者UCS4的BMP必然小於0x10000,所以就目前而言,可以認爲UTF-16和UCS-2基本相同。但UCS-2只是一個編碼方案,UTF-16卻要用於實際的傳輸,所以就不得不考慮字節序的問題。

5、UTF的字節序和BOM
UTF-8以字節爲編碼單元,沒有字節序的問題。UTF-16以兩個字節爲編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的字節序。例如收到一個“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那麼這是“奎”還是“乙”?

Unicode規範中推薦的標記字節順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個有點小聰明的想法:

在UCS編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規範建議我們在傳輸字節流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。

這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。

UTF-8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗證一下)。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。

Windows就是使用BOM來標記文本文件的編碼方式的。

6、進一步的參考資料
本文主要參考的資料是 "Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。

我還找了兩篇看上去不錯的資料,不過因爲我開始的疑問都找到了答案,所以就沒有看:

"Understanding Unicode A general introduction to the Unicode Standard" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=IWS-Chapter04a)
"Character set encoding basics Understanding character set encodings and legacy encodings" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=IWS-Chapter03)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章