posts - 19, comments - 1, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          2006年10月14日

          正則表達式是煩瑣的,但是強大的,學會之后的應用會讓你除了提高效率外,會給你帶來絕對的成就感。只要認真去閱讀這些資料,加上應用的時候進行一定的參考,掌握正則表達式不是問題。

          索引

          1. 引子
          2. 正則表達式的歷史
          3. 正則表達式定義

          3.1 普通字符
          3.2 非打印字符
          3.3 特殊字符
          3.4 限定符
          3.5 定位符
          3.6 選擇
          3.7 后向引用

          4. 各種操作符的運算優先級
          5. 全部符號解釋
          6. 部分例子
          7. 正則表達式匹配規則

          7.1 基本模式匹配
          7.2 字符簇
          7.3 確定重復出現

          1. 引子
            目前,正則表達式已經在很多軟件中得到廣泛的應用,包括*nix(Linux, Unix等),HP等操作系統,PHP,C#,Java等開發環境,以及很多的應用軟件中,都可以看到正則表達式的影子。

            正則表達式的使用,可以通過簡單的辦法來實現強大的功能。為了簡單有效而又不失強大,造成了正則表達式代碼的難度較大,學習起來也不是很容易,所以需要付出一些努力才行,入門之后參照一定的參考,使用起來還是比較簡單有效的。

          例子: ^.+@.+\\..+$

            這樣的代碼曾經多次把我自己給嚇退過。可能很多人也是被這樣的代碼給嚇跑的吧。繼續閱讀本文將讓你也可以自由應用這樣的代碼。

            注意:這里的第7部分跟前面的內容看起來似乎有些重復,目的是把前面表格里的部分重新描述了一次,目的是讓這些內容更容易理解。

          2. 正則表達式的歷史
            正則表達式的“祖先”可以一直上溯至對人類神經系統如何工作的早期研究。Warren McCulloch 和 Walter Pitts 這兩位神經生理學家研究出一種數學方式來描述這些神經網絡。
            1956 年, 一位叫 Stephen Kleene 的數學家在 McCulloch 和 Pitts 早期工作的基礎上,發表了一篇標題為“神經網事件的表示法”的論文,引入了正則表達式的概念。正則表達式就是用來描述他稱為“正則集的代數”的表達式,因此采用“正則表達式”這個術語。

            隨后,發現可以將這一工作應用于使用 Ken Thompson 的計算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要發明人。正則表達式的第一個實用應用程序就是 Unix 中的 qed 編輯器。

            如他們所說,剩下的就是眾所周知的歷史了。從那時起直至現在正則表達式都是基于文本的編輯器和搜索工具中的一個重要部分。

           

          3. 正則表達式定義
            正則表達式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。

          列目錄時, dir *.txt或ls *.txt中的*.txt就不是一個正則表達式,因為這里*與正則式的*的含義是不同的。
            正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。

          3.1 普通字符
            由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫和小寫字母字符,所有數字,所有標點符號以及一些符號。

          3.2 非打印字符
          字符 含義
          \cx 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 ‘c’ 字符。
          \f 匹配一個換頁符。等價于 \x0c 和 \cL。
          \n 匹配一個換行符。等價于 \x0a 和 \cJ。
          \r 匹配一個回車符。等價于 \x0d 和 \cM。
          \s 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。
          \S 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。
          \t 匹配一個制表符。等價于 \x09 和 \cI。
          \v 匹配一個垂直制表符。等價于 \x0b 和 \cK。

           
          3.3 特殊字符
            所謂特殊字符,就是一些有特殊含義的字符,如上面說的”*.txt”中的*,簡單的說就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉義,即在其前加一個\。ls \*.txt。正則表達式有以下特殊字符。
           

          特別字符 說明
          $ 匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,請使用 \$。
          ( ) 標記一個子表達式的開始和結束位置。子表達式可以獲取供以后使用。要匹配這些字符,請使用 \( 和 \)。
          * 匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*。
          + 匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+。
          . 匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \。
          [ 標記一個中括號表達式的開始。要匹配 [,請使用 \[。
          ? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。
          \ 將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉義符。例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配換行符。序列 ‘\\’ 匹配 “\”,而 ‘\(’ 則匹配 “(”。
          ^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^。
          { 標記限定符表達式的開始。要匹配 {,請使用 \{。
          | 指明兩項之間的一個選擇。要匹配 |,請使用 \|。

            構造正則表達式的方法和創建數學表達式的方法一樣。也就是用多種元字符與操作符將小的表達式結合在一起來創建更大的表達式。正則表達式的組件可以是單個的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。
           

          3.4 限定符
            限定符用來指定正則表達式的一個給定組件必須要出現多少次才能滿足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
          *、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的后面加上一個?就可以實現非貪婪或最小匹配。
            正則表達式的限定符有:
            字符 描述
          * 匹配前面的子表達式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等價于{0,}。
          + 匹配前面的子表達式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等價于 {1,}。
          ? 匹配前面的子表達式零次或一次。例如,”do(es)?” 可以匹配 “do” 或 “does” 中的”do” 。? 等價于 {0,1}。
          {n} n 是一個非負整數。匹配確定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的兩個 o。
          {n,} n 是一個非負整數。至少匹配n 次。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等價于 ‘o+’。’o{0,}’ 則等價于 ‘o*’。
          {n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,”o{1,3}” 將匹配 “fooooood” 中的前三個 o。’o{0,1}’ 等價于 ‘o?’。請注意在逗號和兩個數之間不能有空格。

          3.5 定位符
            用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結束,\b描述單詞的前或后邊界,\B表示非單詞邊界。不能對定位符使用限定符。

          3.6 選擇
            用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被緩存,此時可用?:放在第一個選項前來消除這種副作用。
            其中?:是非捕獲元之一,還有兩個非捕獲元是?=和?!,這兩個還有更多的含義,前者為正向預查,在任何開始匹配圓括號內的正則表達式模式的位置來匹配搜索字符串,后者為負向預查,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。

          3.7 后向引用
            對一個正則表達式模式或部分模式兩邊添加圓括號將導致相關匹配存儲到一個臨時緩沖區中,所捕獲的每個子匹配都按照在正則表達式模式中從左至右所遇到的內容存儲。存儲子匹配的緩沖區編號從 1 開始,連續編號直至最大 99 個子表達式。每個緩沖區都可以使用 ‘\n’ 訪問,其中 n 為一個標識特定緩沖區的一位或兩位十進制數。
            可以使用非捕獲元字符 ‘?:’, ‘?=’, or ‘?!’ 來忽略對相關匹配的保存。

          4. 各種操作符的運算優先級
            相同優先級的從左到右進行運算,不同優先級的運算先高后低。各種操作符的優先級從高到低如下:
            操作符 描述
          \ 轉義符
          (), (?:), (?=), [] 圓括號和方括號
          *, +, ?, {n}, {n,}, {n,m} 限定符
          ^, $, \anymetacharacter 位置和順序
          | “或”操作

          5. 全部符號解釋

          字符 描述
          \ 將下一個字符標記為一個特殊字符、或一個原義字符、或一個 向后引用、或一個八進制轉義符。例如,’n’ 匹配字符 “n”。’\n’ 匹配一個換行符。序列 ‘\\’ 匹配 “\” 而 “\(” 則匹配 “(”。
          ^ 匹配輸入字符串的開始位置。如果設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。
          $ 匹配輸入字符串的結束位置。如果設置了RegExp 對象的 Multiline 屬性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。
          * 匹配前面的子表達式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等價于{0,}。
          + 匹配前面的子表達式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等價于 {1,}。
          ? 匹配前面的子表達式零次或一次。例如,”do(es)?” 可以匹配 “do” 或 “does” 中的”do” 。? 等價于 {0,1}。
          {n} n 是一個非負整數。匹配確定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的兩個 o。
          {n,} n 是一個非負整數。至少匹配n 次。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等價于 ‘o+’。’o{0,}’ 則等價于 ‘o*’。
          {n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,”o{1,3}” 將匹配 “fooooood” 中的前三個 o。’o{0,1}’ 等價于 ‘o?’。請注意在逗號和兩個數之間不能有空格。
          ? 當該字符緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對于字符串 “oooo”,’o+?’ 將匹配單個 “o”,而 ‘o+’ 將匹配所有 ‘o’。
          . 匹配除 “\n” 之外的任何單個字符。要匹配包括 ‘\n’ 在內的任何字符,請使用象 ‘[.\n]’ 的模式。
          (pattern) 匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 ‘\(’ 或 ‘\)’。
          (?:pattern) 匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用 “或” 字符 (|) 來組合一個模式的各個部分是很有用。例如, ‘industr(?:y|ies) 就是一個比 ‘industry|industries’ 更簡略的表達式。
          (?=pattern) 正向預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如,’Windows (?=95|98|NT|2000)’ 能匹配 “Windows 2000″ 中的 “Windows” ,但不能匹配 “Windows 3.1″ 中的 “Windows”。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。
          (?!pattern) 負向預查,在任何不匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如’Windows (?!95|98|NT|2000)’ 能匹配 “Windows 3.1″ 中的 “Windows”,但不能匹配 “Windows 2000″ 中的 “Windows”。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始
          x|y 匹配 x 或 y。例如,’z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 則匹配 “zood” 或 “food”。
          [xyz] 字符集合。匹配所包含的任意一個字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
          [^xyz] 負值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p'。
          [a-z] 字符范圍。匹配指定范圍內的任意字符。例如,’[a-z]’ 可以匹配 ‘a’ 到 ‘z’ 范圍內的任意小寫字母字符。
          [^a-z] 負值字符范圍。匹配任何不在指定范圍內的任意字符。例如,’[^a-z]’ 可以匹配任何不在 ‘a’ 到 ‘z’ 范圍內的任意字符。
          \b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
          \B 匹配非單詞邊界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
          \cx 匹配由 x 指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 ‘c’ 字符。
          \d 匹配一個數字字符。等價于 [0-9]。
          \D 匹配一個非數字字符。等價于 [^0-9]。
          \f 匹配一個換頁符。等價于 \x0c 和 \cL。
          \n 匹配一個換行符。等價于 \x0a 和 \cJ。
          \r 匹配一個回車符。等價于 \x0d 和 \cM。
          \s 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。
          \S 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。
          \t 匹配一個制表符。等價于 \x09 和 \cI。
          \v 匹配一個垂直制表符。等價于 \x0b 和 \cK。
          \w 匹配包括下劃線的任何單詞字符。等價于’[A-Za-z0-9_]’。
          \W 匹配任何非單詞字符。等價于 ‘[^A-Za-z0-9_]’。
          \xn 匹配 n,其中 n 為十六進制轉義值。十六進制轉義值必須為確定的兩個數字長。例如,’\x41′ 匹配 “A”。’\x041′ 則等價于 ‘\x04′ & “1″。正則表達式中可以使用 ASCII 編碼。.
          \num 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,’(.)\1′ 匹配兩個連續的相同字符。
          \n 標識一個八進制轉義值或一個向后引用。如果 \n 之前至少 n 個獲取的子表達式,則 n 為向后引用。否則,如果 n 為八進制數字 (0-7),則 n 為一個八進制轉義值。
          \nm 標識一個八進制轉義值或一個向后引用。如果 \nm 之前至少有 nm 個獲得子表達式,則 nm 為向后引用。如果 \nm 之前至少有 n 個獲取,則 n 為一個后跟文字 m 的向后引用。如果前面的條件都不滿足,若 n 和 m 均為八進制數字 (0-7),則 \nm 將匹配八進制轉義值 nm。
          \nml 如果 n 為八進制數字 (0-3),且 m 和 l 均為八進制數字 (0-7),則匹配八進制轉義值 nml。
          \un 匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字符。例如, \u00A9 匹配版權符號 (?)。

           

          6. 部分例子

          正則表達式 說明
          /\b([a-z]+) \1\b/gi 一個單詞連續出現的位置
          /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 將一個URL解析為協議、域、端口及相對路徑
          /^(?:Chapter|Section) [1-9][0-9]{0,1}$/ 定位章節的位置
          /[-a-z]/ A至z共26個字母再加一個-號。
          /ter\b/ 可匹配chapter,而不能terminal
          /\Bapt/ 可匹配chapter,而不能aptitude
          /Windows(?=95 |98 |NT )/ 可匹配Windows95或Windows98或WindowsNT,當找到一個匹配后,從Windows后面開始進行下一次的檢索匹配。

          7. 正則表達式匹配規則
          7.1 基本模式匹配

            一切從最基本的開始。模式,是正規表達式最基本的元素,它們是一組描述字符串特征的字符。模式可以很簡單,由普通的字符串組成,也可以非常復雜,往往用特殊的字符表示一個范圍內的字符、重復出現,或表示上下文。例如:

          ^once

            這個模式包含一個特殊的字符^,表示該模式只匹配那些以once開頭的字符串。例如該模式與字符串”once upon a time”匹配,與”There once was a man from NewYork”不匹配。正如如^符號表示開頭一樣,$符號用來匹配那些以給定模式結尾的字符串。

          bucket$

            這個模式與”Who kept all of this cash in a bucket”匹配,與”buckets”不匹配。字符^和$同時使用時,表示精確匹配(字符串與模式一樣)。例如:

          ^bucket$

            只匹配字符串”bucket”。如果一個模式不包括^和$,那么它與任何包含該模式的字符串匹配。例如:模式

          once

          與字符串

          There once was a man from NewYork
          Who kept all of his cash in a bucket.

          是匹配的。

            在該模式中的字母(o-n-c-e)是字面的字符,也就是說,他們表示該字母本身,數字也是一樣的。其他一些稍微復雜的字符,如標點符號和白字符(空格、制表符等),要用到轉義序列。所有的轉義序列都用反斜杠(\)打頭。制表符的轉義序列是:\t。所以如果我們要檢測一個字符串是否以制表符開頭,可以用這個模式:

          ^\t

          類似的,用\n表示“新行”,\r表示回車。其他的特殊符號,可以用在前面加上反斜杠,如反斜杠本身用\\表示,句號.用\.表示,以此類推。

          7.2 字符簇

          在INTERNET的程序中,正規表達式通常用來驗證用戶的輸入。當用戶提交一個form以后,要判斷輸入的電話號碼、地址、EMAIL地址、信用卡號碼等是否有效,用普通的基于字面的字符是不夠的。

          所以要用一種更自由的描述我們要的模式的辦法,它就是字符簇。要建立一個表示所有元音字符的字符簇,就把所有的元音字符放在一個方括號里:

          [AaEeIiOoUu]

          這個模式與任何元音字符匹配,但只能表示一個字符。用連字號可以表示一個字符的范圍,如:

          [a-z] //匹配所有的小寫字母
          [A-Z] //匹配所有的大寫字母
          [a-zA-Z] //匹配所有的字母
          [0-9] //匹配所有的數字
          [0-9\.\-] //匹配所有的數字,句號和減號
          [ \f\r\t\n] //匹配所有的白字符

          同樣的,這些也只表示一個字符,這是一個非常重要的。如果要匹配一個由一個小寫字母和一位數字組成的字符串,比如”z2″、”t6″或”g7″,但不是”ab2″、”r2d3″ 或”b52″的話,用這個模式:

          ^[a-z][0-9]$

          盡管[a-z]代表26個字母的范圍,但在這里它只能與第一個字符是小寫字母的字符串匹配。

          前面曾經提到^表示字符串的開頭,但它還有另外一個含義。當在一組方括號里使用^是,它表示“非”或“排除”的意思,常常用來剔除某個字符。還用前面的例子,我們要求第一個字符不能是數字:

          ^[^0-9][0-9]$

          這個模式與”&5″、”g7″及”-2″是匹配的,但與”12″、”66″是不匹配的。下面是幾個排除特定字符的例子:

          [^a-z] //除了小寫字母以外的所有字符
          [^\\\/\^] //除了(\)(/)(^)之外的所有字符
          [^\"\'] //除了雙引號(")和單引號(')之外的所有字符

          特殊字符”.” (點,句號)在正規表達式中用來表示除了“新行”之外的所有字符。所以模式”^.5$”與任何兩個字符的、以數字5結尾和以其他非“新行”字符開頭的字符串匹配。模式”.”可以匹配任何字符串,除了空串和只包括一個“新行”的字符串。

          PHP的正規表達式有一些內置的通用字符簇,列表如下:

          字符簇 含義
          [[:alpha:]] 任何字母
          [[:digit:]] 任何數字
          [[:alnum:]] 任何字母和數字
          [[:space:]] 任何白字符
          [[:upper:]] 任何大寫字母
          [[:lower:]] 任何小寫字母
          [[:punct:]] 任何標點符號
          [[:xdigit:]] 任何16進制的數字,相當于[0-9a-fA-F]

          7.3 確定重復出現

          到現在為止,你已經知道如何去匹配一個字母或數字,但更多的情況下,可能要匹配一個單詞或一組數字。一個單詞有若干個字母組成,一組數字有若干個單數組成。跟在字符或字符簇后面的花括號({})用來確定前面的內容的重復出現的次數。

          字符簇 含義
          ^[a-zA-Z_]$ 所有的字母和下劃線
          ^[[:alpha:]]{3}$ 所有的3個字母的單詞
          ^a$ 字母a
          ^a{4}$ aaaa
          ^a{2,4}$ aa,aaa或aaaa
          ^a{1,3}$ a,aa或aaa
          ^a{2,}$ 包含多于兩個a的字符串
          ^a{2,} 如:aardvark和aaab,但apple不行
          a{2,} 如:baad和aaa,但Nantucket不行
          \t{2} 兩個制表符
          .{2} 所有的兩個字符

          這些例子描述了花括號的三種不同的用法。一個數字,{x}的意思是“前面的字符或字符簇只出現x次”;一個數字加逗號,{x,}的意思是“前面的內容出現x或更多的次數”;兩個用逗號分隔的數字,{x,y}表示“前面的內容至少出現x次,但不超過y次”。我們可以把模式擴展到更多的單詞或數字:

          ^[a-zA-Z0-9_]{1,}$ //所有包含一個以上的字母、數字或下劃線的字符串
          ^[0-9]{1,}$ //所有的正數
          ^\-{0,1}[0-9]{1,}$ //所有的整數
          ^\-{0,1}[0-9]{0,}\.{0,1}[0-9]{0,}$ //所有的小數

          最后一個例子不太好理解,是嗎?這么看吧:與所有以一個可選的負號(\-{0,1})開頭(^)、跟著0個或更多的數字([0-9]{0,})、和一個可選的小數點(\.{0,1})再跟上0個或多個數字([0-9]{0,}),并且沒有其他任何東西($)。下面你將知道能夠使用的更為簡單的方法。

          特殊字符”?”與{0,1}是相等的,它們都代表著:“0個或1個前面的內容”或“前面的內容是可選的”。所以剛才的例子可以簡化為:

          ^\-?[0-9]{0,}\.?[0-9]{0,}$

          特殊字符”*”與{0,}是相等的,它們都代表著“0個或多個前面的內容”。最后,字符”+”與 {1,}是相等的,表示“1個或多個前面的內容”,所以上面的4個例子可以寫成:

          ^[a-zA-Z0-9_]+$ //所有包含一個以上的字母、數字或下劃線的字符串
          ^[0-9]+$ //所有的正數
          ^\-?[0-9]+$ //所有的整數
          ^\-?[0-9]*\.?[0-9]*$ //所有的小數

          當然這并不能從技術上降低正規表達式的復雜性,但可以使它們更容易閱讀。

          posted @ 2006-10-14 21:59 xyang 閱讀(380) | 評論 (0)編輯 收藏

          2006年10月10日

          • Liferay - Liferay is designed to deploy portlets that adhere to the Portlet API (JSR 168). Many useful portlets are bundled with the portal (Mail, Document Library, Calendar, Message Boards, to name a few) and can be used as examples for adding your own custom portlets.
          • Exo - The eXo platform is a powerful Open Source - JSR 168 compliant - enterprise portal built from several modules. Based on the most innovative tools, API and frameworks such as Java Server Faces, Pico Container, JbossMX and AspectJ.
          • Pluto - Pluto is the Reference Implementation of the Java Portlet Specfication. The current version of this specification is JSR 168.
          • JA-SIG uPortal - uPortal is a free, sharable portal under development by institutions of higher-education. Community tools, such as chat, forums, survey, and so on, build relationships among campus constituencies. uPortal is an open-standard effort using Java, XML, JSP and J2EE.
          • Redhat Portal Server - Red Hat Portal Server is a open source Portal solution. Supports multiple languages in its user interface and pervasive devices such as WAP, XHTML, and VoiceXML in its rendering pipeline. Portals can be built and targeted for the individual, for work groups or teams, for people with a common set of interests, and for large corporations and organizations.
          • Jakarta Jetspeed 2 Enterprise Portal - Jetspeed is an Open Source implementation of an Enterprise Information Portal, using Java and XML. etspeed-2 is the next-generation enterprise portal at Apache. Jetspeed-2 offers several architectural enhancements and improvements over Jetspeed 1.0. First, Jetspeed-2 is conformant to the Java Portlet Standard and will provide a standard mechanism for the deployment of portlets.
          • Jahia - An integrated web content management and corporate portal server; 100% Java based; Available under a collaborative source license (contribue or pay paradigm); Installed in minutes; Easy to use and to administer; Full Multilanguage and I18N support; Staging environement; Content Workflow; Content Versioning; Document Management (WebDAV Support); Built-in Portlet-based interface; Built-in support for standardized java web applications and web services (default servlets supported as portlets); Full web-based administration; Integrated with the Apache Lucene Search Engine; LDAP compliant; JSP and JSTL support for easy templates development; Integrated HTML cache engine; dynamic XML export module and much more...
          • Gluecode Portal Foundation Server - Gluecode PFS is built in collaboration with the largest open source communities, including JBoss and Apache. It adheres to J2EE specifications, as well as implementations of portal industry standards.
          • jPortlet - jPortlet is not JSR 168 compliant, but the jPortlet API is very similar to the IBM WebSpere Portal Server.
          • GridSphere - 100% JSR 168 Portlet API compliant. Portlet API implementation nearly fully compatible with IBM's WebSphere 4.2. Higher-level model for building complex portlets using visual beans and the GridSphere User Interface (UI) tag library. Built-in support for Role Based Access Control (RBAC) separating users into guests, users, admins and super users. Persistence of data provided using Hibernate for RDBMS database support Integrated Junit/Cactus unit tests. Localization support including English, French, German, Czech, Polish, Hungarian and Italian.
          • Cocoon Portal Framework - Apache Cocoon is a web development framework built around the concepts of separation of concerns and component-based web development. Cocoon implements these concepts around the notion of 'component pipelines', each component on the pipeline specializing on a particular operation. The Portal Framework is based on Cocoon and is rumored to eventually support JSR-168.
          • jPorta - jPorta is a fully functional portal engine built on top of the Jeenius Framework (http://jeenius.sourceforge.net). It works with any 2.3 compilant servlet engine and comes with a number of useful gadgets.
          • MyPersonalizer - MyPersonalizer is a J2EE-based framework. The controller layer is built upon Jakarta Struts. MyPersonalizer also provides a number of command line administration tools for initialization tasks and a web administration tool to administrate any portal built with the framework.
          • oPortal - The OWASP Portal project, oPortal, is a portal written in java that aims to become the standard for secure web applications. The OWASP portal is based on the Jakarta Struts framework and designed with security as a REQUIREMENT, not an option. A reference implementation of a secure portal, that will rival the likes of any commercially available portal. JSR-168 compliance scheduled for version 1.1 release.
          • CHEF - CompreHensive collaborativeE Framework. CHEF is a Java J2EE (Servlet) based application server. The portal engine is a version of Apache's Jetspeed. CHEF is a set of tools and services. Tools control an application's user interface. Services provide information modeling, persistence, and important application logic. The tools are a set of groupware applications (such as chat, schedule and resources). The services specifically support the tools (such as content hosting and messaging) and generally support the application environment (such as authentication, event tracking, security).
          • Siemens Intranet Portal Framework - The Siemens Intranet Portal Framework (SIPF) offers a personalized, structured access to information and seamless integration of applications. A web-based work environment is realized within a browser by hierarchically structured virtual desktops.
          • Lutece - Lutece is a web portal engine that lets you quickly create internet or intranet dynamic sites based on HTML, XML or database contents. This tool, developed by the Data Processing Department of the City of Paris for the districts web sites projects, is now used by more than 18 web sites of the city.
          • Sakai Project - Builds on JSR 168 and OKI open service interface definitions. A re-factored set of educational software tools that blends the best of features from the University of Michigan, Indiana University, MIT, Stanford, and the uPortal consortium. The Sakai Project will include an Enterprise Services-based Portal, a complete Course Management System with sophisticated assessment tools, a Research Support Collaboration System, a Workflow Engine, and a Technology Portability Profile as a clear standard for writing future tools that can extend this core set of educational applications. The Sakai Project Core universities are committing over $2 million per year to launch and support this two year project.
          • JBoss Portal - JBoss Portal 2.0 framework and architecture includes the portal container and supports a wide range of features including standard portlets, single sign-on, clustering and internationalization. Portal themes and layouts are configurable. Fine-grained security administration down to portlet permissions rounds out the security model. JBoss Portal 2.0 includes a rich content management system and message board support.
          • Stringbeans - Stringbeans is a platform for building enterprise information portals. The platform is composed of three components: a portal container/server, a Web Services framework, and a process automation engine. Compatible with JSR 168 standard, mobile client support (WML 1.1 and XHTML MP 1.0), JAAS-based user authentication, portlets capable of displaying RSS headlines, multi-page tabular data from database tables, reports, charts, XML documents via XSL tranformations. Stringbeans is deployed as a J2EE Web application in a container that supports Servlets 2.3 and Java Server Pages (JSP) 1.2 specification. EJB support is not required.
          • InfoGlue 2.0 - InfoGlue is a GPL-based content management and JSR 168 Portal system. Key features includes full multi-language support, excellent information reuse between sites and extensive integration capabilities. A dynamic visual page builder. This release supports advanced workflows as well as very detailed access control both internally and externally.
          • NodeVision Portal - NVPortal is the Java Enterprise JSR 168 compliant Portal solution based on a BSD-License. Features include a Business Process Engine and Search Engine based on SOAP, WSRP compliance, Multilingual, Single Sign On and a Graphical administration interface.
          • Pentaho - The Pentaho BI Project provides enterprise-class reporting, analysis, dashboard, data mining and workflow capabilities that help organizations operate more efficiently and effectively. The software offers flexible deployment options that enable use as embeddable components, customized BI application solutions, and as a complete out-of-the-box, integrated BI platform.
          • IPoint Open Edition - iPoint Open Edition has passed the JSR168 TCK. It is designed so that the portal can be developed within a browser. iPoint portal contains many prebuilt portlets and features complete browser based management and site construction.
          • Portals in Cocoon - The portal framework is a portal server that runs inside Cocoon - or to be more precise inside the Cocoon servlet. It contains a portlet container that is called coplet container. Coplet stands for Cocoon Portlet and is the Cocoon equivalent to portlet. The new portal engine is a replacement implementation of a portal engine which focuses on more flexibility and ease-of-use. In addition it supports the JSR-168.
          • Enterprise-class Portal Server Open Source project - The Portal Server open source project is derived from the Sun Java System Portal Server 7 product and will comprise of the following components and technologies: Portlet repository, JSR168 compliant portlet container, Web Services for Remote Portlets (WSRP) 1.0 based producer and consumer implementations, Portal aggregation and administration framework, Communities and collaboration framework/services, Full-text search engine with federated search and taxonomy capabilities, Secure remote access for SSL/VPN capabilities from outside the firewall and Multi-device mobile access capability to all portal content and applications.

          posted @ 2006-10-10 09:44 xyang 閱讀(674) | 評論 (0)編輯 收藏

          2006年10月9日

          1.?自動裝箱與拆箱?對應C#
          ?例1.1
          ??Integer?i?=?10;
          ??int?j?=?i;
          ??
          2.?更優化的for循環?對應就C#---foreach循環
          ?例2.1
          ??String[]?names?=?{"BadBoy","GoodBoy","HappyGirl","sadGirl"};
          ??for(String?option:?names)?{
          ???System.out.println(option);
          ??}
          ?例2.2?加泛型?對應C++模板
          ??import?java.util.*;
          ??
          ??ArrayList<String>?animals?=?new?ArrayList<String>();
          ??animals.add("Dog");
          ??animals.add("Cat");
          ??animals.add("Chick");
          ??animals.add("Cow");
          ??for(String?option?:?animals)?{
          ???System.out.println(option);
          ??}
          ??
          3.參數可變的方法和printf
          ?例3.1
          ??定義:
          ??public?int?sum(int...?n)?{??//傳過來n為一個int型數組
          ???int?tempSum;
          ???for(int?option?:?n)?{
          ????tempSum+=option;
          ???}
          ???/*
          ???for(int?i?=?0;?i?<?n.length;?i++)?{
          ????tempSum+=n[i];
          ???}
          ???*/
          ???return?tempSum;
          ??}
          ??調用1:?sum(1);
          ??調用2:?sum(1,2);
          ??調用3:?sum(1,2,3,4);
          ?例3.2?printf方法,??對應c語言的printf
          ??int?x?=?10;
          ??int?y?=?20;
          ??int?sum?=?x?+?y;
          ??System.out.printf("%d?+?%d?=?%d",x,y,sum);
          4.?枚舉
          ?例4.1
          ??public?enum?MyColors?{
          ???red,
          ???black,
          ???blue,
          ???green,
          ???yellow
          ??}
          ??
          ??MyColors?color?=?MyColors.red;
          ??for(MyColors?option?:?color.values())?{
          ???System.out.println(option);
          ??}

          /**不能在switch語句里這樣寫case?MyColors.red:
          ?*這樣編譯器不會讓你通過*/
          switch(color)?{
          ?case?red:
          ??System.out.println("best?color?is?"+red);
          ??break;
          ?case?black:
          ??System.out.println("NO?"?+?black);
          ??break;
          ?default:
          ??System.out.println("What");
          ??break;
          }

          5.靜態引用
          ?例5.1
          ??1.5版本以前的寫法是:
          ?
          ??  import?java.lang.Math;?//程序開頭處
          ??
          ??  ...
          ??
          ??  double?x?=?Math.random();?
          ??1.5版本中可以這樣寫
          ???import?static?java.lang.Math.random;?//程序開頭處
          ???
          ???...
          ??  
          ???double?x?=?random();??

          posted @ 2006-10-09 23:05 xyang 閱讀(282) | 評論 (0)編輯 收藏

          這個題目含有許多需要解釋的概念,最容易說明的是“站內消息”,這是很多論壇都有的功能,可以通過web向其他的在線用戶發送消息,很多用戶都使用過。站內消息的第一個好處是大家都不需要安裝客戶端,你不用知道對方的MSN或者QQ,就能與他聯系,稱贊他的觀點或者是給他一頓臭罵。第二個好處是客戶管理方便,利用session來維護在線名單,各種腳本都已經把session操作封裝得很易用了,不用像其他無狀態的即時通信工具(比如使用UDP通信的工具)一樣,要費一些腦細胞來解決在線名單的問題。缺點嘛,就是實時性不好,一般是在用戶跳轉或者刷新頁面才能探測消息、更新在線名單。

            Session監聽嘛,沒什么好解釋的,java提供了很靈活的事件機制來監聽session,可以監聽session的創建和銷毀,監控session所攜帶數據的創建、變化和銷毀,可以監聽session的銳化和鈍化(了解對象序列化的兄弟應該知道這個),其他的平臺是個什么情況我不太清楚,估計也差不多吧。如果能夠對所有客戶的session進行監控,就不用再去操作麻煩而危險的Application了。

            Xmlhttp是MS推的一項技術,功能很復雜,可以做很多事情,比如客戶端可以在簡單的HTML中打開HTTP連接,主動向server請求數據并獲得返回數據,是DOM技術一個非常重要的應用,利用它來寫無刷新的動態頁面簡直是so?easy,做過web開發的兄弟應該明白它的意義有多么重大。

          一、?session監聽

            servlet中對session的監聽有很多接口,功能很靈活,最常用的是監聽Session和Attribute。這里要澄清一下概念,servlet中的session監聽和Attribute監聽含義有差別,session監聽指的不是我們一般所理解的放置一個session或者銷毀一個session,這是Attribute監聽的功能,因為servlet中放置session的語法是session.setAttribute(“session名”,要放入的對象)。而session監聽,監聽的是HTTP連接,只要有用戶與server連接,就算連接的是一個空白的jsp頁面,也會觸發session事件,所以此處的session實際上指的是connection,用來統計當前在線用戶數最合適了。不知道我說清楚了沒有。下面分別講解這兩種監聽方式。

          1、?session監聽

            首先編寫一個session監聽類,實作HttpSessionListener接口,它的作用是計算當前有多少個在線用戶:

          1. /**
          2. *@Author?bromon
          3. *2004-6-12
          4. */
          5. package?org.bromon.test;
          6. import?javax.servlet.*;
          7. import?javax.servlet.http.*;
          8. public?class?SessionCount?implements?HttpSessionListener
          9. {
          10. ????private?static?int?count=0;
          11. ????public?void?sessionCreated(HttpSessionEvent?se)
          12. ????{
          13. ????????count++;
          14. ????????System.out.println(“session創建:”+new?java.util.Date());
          15. ????}
          16. ????public?void?sessionDestroyed(HttpSessionEvent?se)
          17. ????{
          18. ???????count--;
          19. ???????System.out.println(“session銷毀:”+new?java.util.Date());
          20. ????}
          21. ????public?static?int?getCount()
          22. ????{
          23. ???????return(count);
          24. ?????}
          25. }



            怎么樣,是不是一目了然?count被定義為static,是因為要保證整個系統只有這一個count。如果你實在不放心,可以把它寫成一個單例類。

            然后在web.xml中聲明這個監聽器:
          <listener>
          <listener-class>
          org.bromon.test.SessionCount
          </listener-class>
          </listener>

            編寫一個測試頁面test.jsp,內容是獲得count:
          <%
          int?count=org.bromon.test.SessionCount.getCount();
          out.println(count);
          %>

            需要注意的是,這里根本不涉及任何session的操作。重啟動App?server,試著連接test.jsp,可以看到監聽器已經開始工作。

          2、?Attribute監聽
            作為一個站內消息系統,肯定要獲得所有登陸者的ID,才有可能互發消息。這就涉及Attribute監聽。假設我們寫了個用戶登陸的模塊,用戶通過身份驗證之后會產生一個session,保存它的相關信息,比如:
          1. //check.jsp
          2. <%
          3. ????String?name=request.getParameter(“name”);
          4. ????Name=new?String(name.getBytes(“ISO8859-1”));
          5. ????session.setAttribute(“user”,name);
          6. %>


            做過jsp的兄弟應該對這段代碼再熟悉不過了,下面寫個監聽器來監聽用戶登陸,把所有用戶的ID保存到一個List當中,這個監聽器實作HttpSessionAttributeListener接口:

          1. /**
          2. *@Author?bromon
          3. *2004-6-12
          4. */
          5. package?org.bromon.test;
          6. import?javax.servlet.*;
          7. import?javax.servlet.http.*;
          8. import?java.util.*;
          9. public?class?OnlineList?implements?HttpSessionAttributeListener
          10. {
          11. ????private?static?List?list=new?ArrayList();
          12. ????public?void?attributeAdded(HttpSessionBindingEvent?se)
          13. ????{
          14. ????????if(“user”.equals(se.getName()))
          15. ????????{
          16. ????????????list.add(se.getValue());
          17. ?????????}
          18. ????}
          19. ????public?void?attributeRemoved(HttpSessionBindingEvent?se)
          20. ????{
          21. ?????????if(“user”.equals(se.getName()))
          22. ?????????{
          23. ????????????list.remove(se.getValue());
          24. ?????????}
          25. ????}
          26. ????public?void?attributeReplaced(HttpSessionBindingEvent?se){}
          27. ????public?static?List?getList()
          28. ????{
          29. ?????????return(list);
          30. ?????}
          31. }


          寫個簡單的jsp來得到用戶列表:
          <%
          ????java.util.List?list=org.bromon.test.OnlineList.getList();
          ????out.println(“共有”+list.size()+”名用戶已登陸:”);
          ????for(int?I=0;I<lise.size();i++)
          ????{
          ????????out.println(list.get(i));
          ????}
          %>

          也許你說,這有什么神奇呢,監聽session而已,不著急,看看xmlhttp。

          二、?XMLHTTP

            XMLHTTP的用處很多,這里只說我們需要的,就是無刷新的與server通信,看這段代碼:

          1. <script?language="javascript">?
          2. xml?=?new?ActiveXObject("Microsoft.XMLHTTP");?
          3. var?post="?";//構造要攜帶的數據?
          4. xml.open("POST","http://localhost:7001/TestWL/index.jsp",false);//使用POST方法打開一個到服務器的連接,以異步方式通信?
          5. xml.setrequestheader("content-length",post.length);?
          6. xml.setrequestheader("content-type","application/x-www-form-urlencoded");?
          7. xml.send(post);//發送數據?
          8. var?res?=?xml.responseText;//接收服務器返回的數據?
          9. document.write(res);?
          10. </script>



            豁然開朗,這段代碼就是打開一個HTTP連接,以標準的HTTP格式傳遞數據,如果你喜歡,可以用XML的格式來傳遞。更改一下xml對象的構造方式就可以兼容Mozilla和Netscape。下面來寫一個輪詢,每隔一段時間刷新一次用戶列表,當然,是不需要刷新頁面的:

          1. <html>
          2. <head><title>探測器</title>
          3. <script?language="javascript">
          4. function?detect()
          5. {
          6. xml?=?new?ActiveXObject("Microsoft.XMLHTTP");?
          7. var?post="?";//構造要攜帶的數據?
          8. xml.open("POST","http://localhost:7001/TestWL/index.jsp",false);//使用POST方法打開一個到服務器的連接,以異步方式通信?
          9. xml.setrequestheader("content-length",post.length);?
          10. xml.setrequestheader("content-type","application/x-www-form-urlencoded");?
          11. xml.send(post);//發送數據?
          12. var?res?=?xml.responseText;//接收服務器返回的數據?
          13. list.innerText=res;
          14. setTimeout(“detect()”,5000);//每隔5秒鐘輪詢一次
          15. }?
          16. </script>
          17. <body?onload=”detect()”>
          18. <a?id=”list”></a>
          19. </body>
          20. </html>
          21. 這樣的通信方式數據量很小,不用重新傳遞整個頁面,5秒鐘輪一次,普通PC也能承受較大的在線數。構造一個探測器來監聽在線列表和消息,效果是很好的,即使你的客戶坐在電腦前袖手旁觀,鍵鼠都不碰一下,也能保證數據即時傳遞,頁面也不會發生跳轉和刷新。

              Session監聽加上XMLHTTP通信,開發一個較為完善的站內消息系統實在易如反掌

          posted @ 2006-10-09 22:58 xyang 閱讀(1426) | 評論 (1)編輯 收藏

          2006年10月7日

          計算機常用英語
          計算機常用英語術語、詞匯表
          Computer Vocabulary In Common [color=darkblue][/color]Use
          一、硬件類(Hardware)
          二、軟件類(Software)
          三、網絡類(Network)
          四、其它

          CPU(Center Processor Unit)中央處理單元
          mainboard主板
          RAM(random access
          memory)隨機存儲器(內存)
          ROM(Read Only Memory)只讀存儲器
          Floppy Disk軟盤
          Hard Disk硬盤
          CD-ROM光盤驅動器(光驅)
          monitor監視器
          keyboard鍵盤
          mouse鼠標
          chip芯片
          CD-R光盤刻錄機
          HUB集線器
          Modem= MOdulator-DEModulator,調制解調器
          P-P(Plug and Play)即插即用
          UPS(Uninterruptable Power Supply)不間斷電源
          BIOS(Basic-input-Output
          System)基本輸入輸出系統
          CMOS(Complementary Metal-Oxide-Semiconductor)互補金屬氧化物半導體
          setup安裝
          uninstall卸載
          wizzard向導
          OS(Operation Systrem)操作系統
          OA(Office AutoMation)辦公自動化
          exit退出
          edit編輯
          copy復制
          cut剪切
          paste粘貼
          delete刪除
          select選擇
          find查找
          select all全選
          replace替換
          undo撤消
          redo重做
          program程序
          license許可(證)
          back前一步
          next下一步
          finish結束
          folder文件夾
          Destination Folder目的文件夾
          user用戶
          click點擊
          double click雙擊
          right click右擊
          settings設置
          update更新
          release發布
          data數據
          data base數據庫
          DBMS(Data Base Manege
          System)數據庫管理系統
          view視圖
          insert插入
          object對象
          configuration配置
          command命令
          document文檔
          POST(power-on-self-test)電源自檢程序
          cursor光標
          attribute屬性
          icon圖標
          service pack服務補丁
          option pack功能補丁
          Demo演示
          short cut快捷方式
          exception異常
          debug調試
          previous前一個
          column行
          row列
          restart重新啟動
          text文本
          font字體
          size大小
          scale比例
          interface界面
          function函數
          access訪問
          manual指南
          active激活
          computer language計算機語言
          menu菜單
          GUI(graphical user
          interfaces )圖形用戶界面
          template模版
          page setup頁面設置
          password口令
          code密碼
          print preview打印預覽
          zoom in放大
          zoom out縮小
          pan漫游
          cruise漫游
          full screen全屏
          tool bar工具條
          status bar狀態條
          ruler標尺
          table表
          paragraph段落
          symbol符號
          style風格
          execute執行
          graphics圖形
          image圖像
          Unix用于服務器的一種操作系統
          Mac OS蘋果公司開發的操作系統
          OO(Object-Oriented)面向對象
          virus病毒
          file文件
          open打開
          colse關閉
          new新建
          save保存
          exit退出
          clear清除
          default默認
          LAN局域網
          WAN廣域網
          Client/Server客戶機/服務器
          ATM( Asynchronous
          Transfer Mode)異步傳輸模式
          Windows NT微軟公司的網絡操作系統
          Internet互聯網
          WWW(World Wide Web)萬維網
          protocol協議
          HTTP超文本傳輸協議
          FTP文件傳輸協議
          Browser瀏覽器
          homepage主頁
          Webpage網頁
          website網站
          URL在Internet的WWW服務程序上
          用于指定信息位置的表示方法
          Online在線
          Email電子郵件
          ICQ網上尋呼
          Firewall防火墻
          Gateway網關
          HTML超文本標識語言
          hypertext超文本
          hyperlink超級鏈接
          IP(Address)互聯網協議(地址)
          SearchEngine搜索引擎
          TCP/IP用于網絡的一組通訊協議
          Telnet遠程登錄
          IE(Internet Explorer)探索者(微軟公司的網絡瀏覽器)
          Navigator引航者(網景公司的瀏覽器)
          multimedia多媒體
          ISO國際標準化組織
          ANSI美國國家標準協會
          able 能
          activefile 活動文件
          addwatch 添加監視點
          allfiles 所有文件
          allrightsreserved 所有的權力保留
          altdirlst 切換目錄格式
          andfixamuchwiderrangeofdiskproblems 并能夠解決更大范圍內的磁盤問題
          andotherinFORMation 以及其它的信息
          archivefileattribute 歸檔文件屬性
          assignto 指定到
          autoanswer 自動應答
          autodetect 自動檢測
          autoindent 自動縮進
          autosave 自動存儲
          availableonvolume 該盤剩余空間
          badcommand 命令錯
          badcommandorfilename 命令或文件名錯
          batchparameters 批處理參數
          binaryfile 二進制文件
          binaryfiles 二進制文件
          borlandinternational borland國際公司
          bottommargin 頁下空白
          bydate 按日期
          byextension 按擴展名
          byname 按名稱
          bytesfree 字節空閑
          callstack 調用棧
          casesensitive 區分大小寫
          causespromptingtoconfirmyouwanttooverwritean 要求出現確認提示,在你想覆蓋一個
          centralpointsoftwareinc central point 軟件股份公司
          changedirectory 更換目錄
          changedrive 改變驅動器
          changename 更改名稱
          characterset 字符集
          checkingfor 正在檢查
          checksadiskanddisplaysastatusreport 檢查磁盤并顯示一個狀態報告
          chgdrivepath 改變盤/路徑
          china 中國
          chooseoneofthefollowing 從下列中選一項
          clearall 全部清除
          clearallbreakpoints 清除所有斷點
          clearsanattribute 清除屬性
          clearscommandhistory 清除命令歷史
          clearscreen 清除屏幕
          closeall 關閉所有文件
          codegeneration 代碼生成
          colorpalette 彩色調色板
          commandline 命令行
          commandprompt 命令提示符
          compressedfile 壓縮文件
          configuresaharddiskforusewithmsdos 配置硬盤,以為 MS-DOS 所用
          conventionalmemory 常規內存
          copiesdirectoriesandsubdirectorie***ceptemptyones 拷貝目錄和子目錄,空的除外
          copiesfileswiththearchiveattributeset 拷貝設置了歸檔屬性的文件
          copiesoneormorefilestoanotherlocation 把文件拷貝或搬移至另一地方
          copiesthecontentsofonefloppydisktoanother 把一個軟盤的內容拷貝到另一個軟盤上
          copydiskette 復制磁盤
          copymovecompfindrenamedeletevervieweditattribwordpprintlist C拷貝M移動 O比 F搜索R改名 D刪除 V版本 E瀏覽A屬性 W寫字 P打印 L列表
          copyrightc 版權(c
          createdospartitionorlogicaldosdrive 創建DOS分區或邏輯DOS驅動器
          createextendeddospartition 創建擴展DOS分區
          createlogicaldosdrivesintheextendeddospartition 在擴展DOS分區中創建邏輯DOS驅動器
          createprimarydospartition 創建DOS主分區
          createsadirectory 創建一個目錄
          createschangesordeletesthevolumelabelofadisk 創建,改變或刪除磁盤的卷標
          currentfile 當前文件
          currentfixeddiskdrive 當前硬盤驅動器
          currentsettings 當前設置
          currenttime 當前時間
          cursorposition 光標位置
          defrag 整理碎片
          dele 刪去
          deletepartitionorlogicaldosdrive 刪除分區或邏輯DOS驅動器
          deletesadirectoryandallthesubdirectoriesandfilesinit 刪除一個目錄和所有的子目錄及其中的所有文件
          deltree 刪除樹
          devicedriver 設備驅動程序
          dialogbox 對話欄
          directionkeys 方向鍵
          directly 直接地
          directorylistargument 目錄顯示變量
          directoryof 目錄清單
          directorystructure 目錄結構
          diskaccess 磁盤存取
          diskcopy 磁盤拷貝
          diskservicescopycomparefindrenameverifyvieweditmaplocateinitialize 磁盤服務功能: C拷貝 O比較 F搜索R改卷名V校驗 瀏覽E編緝M圖 L找文件 N格式化
          diskspace 磁盤空間
          displayfile 顯示文件
          displayoptions 顯示選項
          displaypartitioninFORMation 顯示分區信息
          displaysfilesinspecifieddirectoryandallsubdirectories 顯示指定目錄和所有目錄下的文件
          displaysfileswithspecifiedattributes 顯示指定屬性的文件
          displaysorchangesfileattributes 顯示或改變文件屬性
          displaysorsetsthedate 顯示或設備日期
          displayssetupscreensinmonochromeinsteadofcolor 以單色而非彩色顯示安裝屏信息
          displaystheamountofusedandfreememoryinyoursystem 顯示系統中已用和未用的內存數量
          displaysthefullpathandnameofeveryfileonthedisk 顯示磁盤上所有文件的完整路徑和名稱
          displaysthenameoforchangesthecurrentdirectory 顯示或改變當前目錄
          doctor 醫生
          doesn 不
          doesntchangetheattribute 不要改變屬性
          dosshell DOS 外殼
          doubleclick 雙擊
          doyouwanttodisplaythelogicaldriveinFORMationyn 你想顯示邏輯驅動器信息嗎(y/n)?
          driveletter 驅動器名
          editmenu 編輯選單
          emsmemory ems內存
          endoffile 文件尾
          endofline 行尾
          enterchoice 輸入選擇
          entiredisk 轉換磁盤
          environmentvariable 環境變量
          esc esc
          everyfileandsubdirectory 所有的文件和子目錄
          existingdestinationfile 已存在的目錄文件時
          expandedmemory 擴充內存
          expandtabs 擴充標簽
          explicitly 明確地
          extendedmemory 擴展內存
          fastest 最快的
          fatfilesystem fat 文件系統
          fdiskoptions fdisk選項
          fileattributes 文件屬性
          fileFORMat 文件格式
          filefunctions 文件功能
          fileselection 文件選擇
          fileselectionargument 文件選擇變元
          filesin 文件在
          filesinsubdir 子目錄中文件
          fileslisted 列出文件
          filespec 文件說明
          filespecification 文件標識
          filesselected 選中文件
          findfile 文件查尋
          fixeddisk 硬盤
          fixeddisksetupprogram 硬盤安裝程序
          fixeserrorsonthedisk 解決磁盤錯誤
          floppydisk 軟盤
          FORMatdiskette 格式化磁盤
          FORMatsadiskforusewithmsdos 格式化用于MS-DOS的磁盤
          FORMfeed 進紙
          freememory 閑置內存
          fullscreen 全屏幕
          functionprocedure 函數過程
          graphical 圖解的
          graphicslibrary 圖形庫
          groupdirectoriesfirst 先顯示目錄組
          hangup 掛斷
          harddisk 硬盤
          hardwaredetection 硬件檢測
          hasbeen 已經
          helpfile 幫助文件
          helpindex 幫助索引
          helpinFORMation 幫助信息
          helppath 幫助路徑
          helpscreen 幫助屏
          helptext 幫助說明
          helptopics 幫助主題
          helpwindow 幫助窗口
          hiddenfile 隱含文件
          hiddenfileattribute 隱含文件屬性
          hiddenfiles 隱含文件
          howto 操作方式
          ignorecase 忽略大小寫
          inbothconventionalanduppermemory 在常規和上位內存
          incorrectdos 不正確的DOS
          incorrectdosversion DOS 版本不正確
          indicatesabinaryfile 表示是一個二進制文件
          indicatesanasciitextfile 表示是一個ascii文本文件
          insertmode 插入方式
          insteadofusingchkdsktryusingscandisk 請用scandisk,不要用chkdsk
          inuse 在使用
          invaliddirectory 無效的目錄
          is 是
          kbytes 千字節
          keyboardtype 鍵盤類型
          labeldisk 標注磁盤
          laptop 膝上
          largestexecutableprogram 最大可執行程序
          largestmemoryblockavailable 最大內存塊可用
          lefthanded 左手習慣
          leftmargin 左邊界
          linenumber 行號
          linenumbers 行號
          linespacing 行間距
          listbyfilesinsortedorder 按指定順序顯示文件
          listfile 列表文件
          listof 清單
          locatefile 文件定位
          lookat 查看
          lookup 查找
          macroname 宏名字
          makedirectory 創建目錄
          memoryinfo 內存信息
          memorymodel 內存模式
          menubar 菜單條
          menucommand 菜單命令
          menus 菜單
          messagewindow 信息窗口
          microsoft 微軟
          microsoftantivirus 微軟反病毒軟件
          microsoftcorporation 微軟公司
          mini 小的
          modemsetup 調制解調器安裝
          modulename 模塊名
          monitor mode 監控狀態
          monochromemonitor 單色監視器
          move to 移至
          multi 多
          newdata 新建數據
          newer 更新的
          newfile 新文件
          newname 新名稱
          newwindow 新建窗口
          norton norton
          nostack 棧未定義
          noteusedeltreecautiously 注意:小心使用deltree
          onlinehelp 聯機求助
          optionally 可選擇地
          or 或
          pageframe 頁面
          pagelength 頁長
          pausesaftereachscreenfulofinFORMation 在顯示每屏信息后暫停一下
          pctools pc工具
          postscript 附言
          prefixmeaningnot 前綴意即\"不
          prefixtoreverseorder 反向顯示的前綴
          presetswitchesbyprefixinganyswitchwithhyphenforexamplew 用前綴和放在短橫線-后的開關(例如/-w)預置開關
          pressakeytoresume 按一鍵繼續
          pressanykeyforfilefunctions 敲任意鍵執行文件功能
          pressentertokeepthesamedate 敲回車以保持相同的日期
          pressentertokeepthesametime 敲回車以保持相同的時間
          pressesctocontinue 敲esc繼續
          pressesctoexit 敲<esc>鍵退出
          pressesctoexitfdisk 敲esc退出fdisk
          pressesctoreturntofdiskoptions 敲esc返回fdisk選項
          previously 在以前
          printall 全部打印
          printdevice 打印設備
          printerport 打印機端口
          processesfilesinalldirectoriesinthespecifiedpath 在指定的路徑下處理所有目錄下的文件
          programfile 程序文件
          programmingenvironment 程序設計環境
          promptsyoubeforecreatingeachdestinationfile 在創建每個目標文件時提醒你
          promptsyoutopressakeybeforecopying 在拷貝前提示你敲一下鍵
          pulldown 下拉
          pulldownmenus 下拉式選單
          quickFORMat 快速格式化
          quickview 快速查看
          readonlyfile 只讀文件
          readonlyfileattribute 只讀文件屬性
          readonlyfiles 只讀文件
          readonlymode 只讀方式
          redial 重撥
          repeatlastfind 重復上次查找
          reportfile 報表文件
          resize 調整大小
          respectively 分別地
          rightmargin 右邊距
          rootdirectory 根目錄
          runsdebugaprogramtestingandeditingtool 運行debug, 它是一個測試和編輯工具
          runtimeerror 運行時出錯
          save all 全部保存
          save as 另存為
          scandisk 磁盤掃描程序
          scandiskcanreliablydetect scandisk可以可靠地發現
          screencolors 屏幕色彩
          screenoptions 屏幕任選項
          screensaver 屏幕暫存器
          screensavers 屏幕保護程序
          screensize 屏幕大小
          scrollbars 翻卷欄
          scrolllockoff 滾屏已鎖定
          searchfor 搜索
          sectorspertrack 每道扇區數
          selectgroup 選定組
          selectionbar 選擇欄
          setactivepartition 設置活動分區
          setupoptions 安裝選項
          shortcutkeys 快捷鍵
          showclipboard 顯示剪貼板
          singleside 單面
          sizemove 大小/移動
          sorthelp S排序H幫助
          sortorder 順序

          posted @ 2006-10-07 21:22 xyang 閱讀(350) | 評論 (0)編輯 收藏

          2006年9月30日

          HashTable的應用非常廣泛,HashMap是新框架中用來代替HashTable的類,也就是說建議使用HashMap,不要使用HashTable。可能你覺得HashTable很好用,為什么不用呢?這里簡單分析他們的區別。?
          1.HashTable的方法是同步的,HashMap未經同步,所以在多線程場合要手動同步HashMap這個區別就像Vector和ArrayList一樣。

          2.HashTable不允許null值(key和value都不可以),HashMap允許null值(key和value都可以)。

          3.HashTable有一個contains(Object?value),功能和containsValue(Object?value)功能一樣。

          4.HashTable使用Enumeration,HashMap使用Iterator。

          以上只是表面的不同,它們的實現也有很大的不同。

          5.HashTable中hash數組默認大小是11,增加的方式是?old*2+1。HashMap中hash數組的默認大小是16,而且一定是2的指數。

          6.哈希值的使用不同,HashTable直接使用對象的hashCode,代碼是這樣的:
          int?hash?=?key.hashCode();
          int?index?=?(hash?&?0x7FFFFFFF)?%?tab.length;
          而HashMap重新計算hash值,而且用與代替求模:
          int?hash?=?hash(k);
          int?i?=?indexFor(hash,?table.length);

          static?int?hash(Object?x)?{
            int?h?=?x.hashCode();

            h?+=?~(h?<<?9);
            h?^=?(h?>>>?14);
            h?+=?(h?<<?4);
            h?^=?(h?>>>?10);
            return?h;
          }
          static?int?indexFor(int?h,?int?length)?{
            return?h?&?(length-1);
          }
          以上只是一些比較突出的區別,當然他們的實現上還是有很多不同的,比如
          HashMap對null的操作

          posted @ 2006-09-30 21:44 xyang 閱讀(929) | 評論 (0)編輯 收藏

          2006年9月28日

          ?1 public ? class ?hello? {
          ?2 ???? public ? static ? void ?main(String?a[])? throws ?java.io.IOException? {
          ?3 ????????String?tmp? = ? " 中文 " ;?
          ?4 ????????printHex(tmp, " Unicode " );
          ?5 ????????printHex(tmp, " GB2312 " );
          ?6 ????????printHex(tmp, " ISO8859-1 " );
          ?7 ????????printHex(tmp, " UTF-8 " );
          ?8 ????}

          ?9
          10 ???? private ? static ? void ?printHex(String?str,String?charset)? throws ?java.io.IOException? {
          11 ???????? byte []?buf? = ?str.getBytes(charset);
          12 ???????? for ?( int ?i? = ? 0 ;?i? < ?buf.length;?i ++ )? {
          13 ????????????System.out.print(Integer.toHexString(buf[i]));
          14 ????????????System.out.print( " ? " );
          15 ????????}

          16 ????????System.out.println( " ? " );
          17 ????}

          18
          19 }

          posted @ 2006-09-28 13:42 xyang 閱讀(224) | 評論 (0)編輯 收藏

          [概述]
          ????? 計算機中的一切都是以數字來表示的,字符同樣如此。字符編碼就是將字符集編碼成為數字序列,以便能讓計算機識別。各個地區和國家使用的語言有別,將本地使用的語言符號進行編碼就得到本地編碼字符集。例如西歐國家使用的本地編碼是ISO8859-1,中國大陸和新加坡等地區使用本地編碼是GB2312或GBK,中國港臺地區使用的本地編碼是BIG5,韓國和日本的本地編碼分別是euc-kr和Shift_JIS。電腦的操作系統支持各種本地編碼字符集,操作系統默認的本地編碼和你所安裝的操作系統語言版本是一致的。本地集只對本地使用的文字符號進行了編碼,并不包括其他地區使用的文字,即使兩個本地集中包含了相同的字符,這個字符的編碼值也是不同的。例如“中”的GB2312或GBK編碼值為“0xD6D0”,而BIG5編碼值為“0xA4A4”。
          ????? 全球信息交流與融合的趨勢要求實現對本地字符集的統一,1984年4月ISO成立了工作組,針對各國文字、符號進行統一編碼,這種編碼成為Unicode。Unicode于1992年6月通過DIS(DrafInternationalStandard),V2.0版本于1996年發布。Unicode編碼包括了符號6811個、漢字20902個、韓文11172個、等等。Unicode雖然實現了全球統一編碼,但是在字符集數量和編碼效率方面顯然存在著不足,而UTF-8、UTF-16就是針對Unicode編碼進行轉換或擴充形成的編碼,UTF是Unicode Translation Format的縮寫。
          ?
          [細節]
          關于ASCII編碼
          ????? ASCII編碼是美國標準信息交換碼,這種編碼方式針對的是英文字符。ASCII編碼使用一個字節對字符進行編碼,而且字節的最高位都為0,因此ASCII編碼的字符集大小是128個。由于英文字母僅有26個,再加上其他一些常用符號,總大小也不會超過128個,因此ASCII編碼的空間是足夠的。例如,字符“a”被編碼為0x61,字符“b”被編碼為0x62等等。注意,在有的時候ASCII泛指本地編碼,例如文本編輯器UltraEdit中有諸如“ASCII轉Unicode”的功能,這里的ASCII就泛指本地編碼,如果本地編碼是GBK,這個功能執行的就是GBK編碼到Unicode編碼的轉換。
          ?
          關于ISO8859-1編碼
          ????? ISO8859-1是西歐語系國家通用的字符集編碼,ISO8859-1使用一個字節對字符進行編碼,編碼值范圍是0x00-0xFF。其中,0x00-0x1F用作控制字,0x20-0x7F表示字母、數字和符號這些圖形字符,0xA0-0xFF作為附加部分使用。由于ASCII編碼只使用了一個字節中的低7位,編碼范圍僅為0-127,雖然可以容納英文字符和其他的一些符號,但是卻不能包含除英文以外的其他西歐語言的字母,因此ASCII編碼在西歐國家并不通用。針對這個問題ISO在ASCII編碼的基礎上進行了擴充,制定了ISO8859-1編碼,ISO8859-1編碼使用了一個字節的全部8位,編碼范圍是0-255,能包含西歐語系的所有字母和符號。
          ?
          關于GB2312、GBK和BIG5編碼
          ????? GB2312碼是中華人民共和國國家漢字信息交換使用碼,全稱《信息交換使用漢字編碼字符集-基本集》,由國家標準總局發布,1981年5月1日實施,中國大陸和新加坡等地使用此編碼。GB2312收錄了簡化漢字、符號、字母、日文假名等共計7445個字符,其中漢字占6763個。GB2312將代碼表分區94個區(0xA1-0xFE),對應第一個字節,每個區94個位(0xA1-0xFE),對應了第二字節,兩個字節的值分別為區號的值和位號的值加32(0x20),因此也被稱為區位碼。GB2312的編碼范7圍是0x2121-0x777E,與ASCII有重疊,通常方法是將GB碼的兩個字節的最高位置1區別。
          ????? GBK是GB2312-80的擴展,向上兼容,包含了20902個漢字,編碼范圍是0x8140-0xFEFE,剔除高位0x80的字位,其他字符都可以一一映射到Unicode2.0。GB18030-2000(GBK2K)在GBK的基礎上增加了藏、蒙等少數民族的字符,GBK2K從根本上解決了字位不夠、字形不足的問題。GBK2K首先要求實現能夠完全映射到Unicode3.0標準的所有字形,現在還沒有任何一個操作系統支持GBK2K。
          ??????BIG5碼被稱為大五碼,是中國港臺地區使用的字符編碼方式。TW-BIG5碼將所有字分為兩大群,即常用字區和次常用字區,每個字區分都采用筆畫排序,同筆畫的字依部首排序。TW-BIG5每個字由兩個字節組成,第一個字節編碼范圍是0xA1-0xF9,第二個字節編碼范圍是0x40-0x7E和0xA1-0xFE,共計收入13868個字,其中包括5401個常用字、7652個次常用字、7個擴充字、以及808個其他符號。
          ?
          關于Unicode編碼
          ????? ISO(國際化標準組織)將全世界所有的符號進行統一編碼,稱為Unicode編碼。Unicode編碼的字符占用兩個字符的大小,對于ASCII碼表示的字符,Unicode只是簡單的在ASCII碼原來的一個字節碼值上增加一個所有位全為0的字節。Unicode使用兩個字節編碼,因此能表示的字符集最大為65536,另外Unicode中還保留兩千多個數值未用于字符編碼。由于Unicode編碼的空間有限,只能包含各個地區常用的字符而非所有字符,因此,在相當長的一段時間里,本地化字符編碼和Unicode編碼將共存。
          ?
          關于UTF-8和UTF-16編碼
          ????? UTF-8和UTF-16編碼仍然屬于Unicode編碼,它們是在Unicode編碼基礎上進行了轉換或擴展。例如在Windows XP和2000操作系統中,Unicode編碼指的就是UTF-16編碼。
          ????? UTF-8編碼是將Unicode編碼中不同范圍的字符采用不同的字節進行編碼,對于ASCII編碼的字符仍使用一個字節進行編碼,UTF-8編碼完全兼容ASCII編碼。與Unicode想比較,UTF-8編碼使得英文文檔的占用空間減小了一半,因此UTF-8頗受英語系國家的青睞。除此之外,UTF-8編碼中不會出現值為0x0000的數據,這樣避免了和某些程序語言產生沖突,而UTF-8編碼的補充位使得數據能夠被方便的檢測出傳輸過程中是否發生錯誤。通常,UTF-8編碼都使用“EF BB BF”三個字節數據作為文件開頭。

          ????? Unicode編碼和UTF-8編碼結構的對應關系如下:
          ??????? Unicode編碼值???????????????????????? UTF-8編碼結構
          ????? ? \u0001 - \u007E??????????????????????0XXXXXXX
          ????? ? \u0080 - \u07FF 和 \u0000???????110XXXXX 10XXXXXX
          ??????? \u0800 - \uFFFF??????????????????????1110XXXX 10XXXXXX 10XXXXXX
          ?
          ????? Unicode編碼與UTF-8編碼的轉換如下(U8代表UTF-8編碼,U代表Unicode編碼):
          ????? 1) 位于Unicode編碼空間 \u0001-\u007F之間的字符(即編碼使用位小于8位的字符),UTF-8采用一個字節對這些字符進行編碼。直接將Unicode編碼的低位取出就得到了UTF-8編碼。轉換過程可表示為:U8 = (byte)U。
          ????? 2) 位于Unicode編碼空間\u0080-\u07FF之間的字符以及\u0000表示的字符(即編碼使用位為8-11位的字符,以及空字符),UTF-8采用兩個字節對這些字符進行編碼。這時候,將Unicode編碼轉換為UTF-8編碼的方法是:將Unicode編碼的低6位取出,在前面補充“10”作為低字節;將7-11位取出,在前面補充“110”作為高字節。轉換過程可表示為:U8 = [(byte)(0xC0 | (0x01F & (U>>6)),(byte)(0x80 | (0x3F & U)]。
          ????? 3) 位于Unicode編碼空間\u080-\uFFFF之間的字符(即編碼使用位為12-16位的字符),UTF-8采用三個字節對這些字符進行編碼。這時候,將Unicode編碼轉換為UTF-8編碼的方法是:將Unicode編碼的低6位取出,在前面補充“10”作為低字節;將7-12位取出,在前面補充“10”作為中字節;將13-16位取出,在前面補充“1110”作為高字節。轉換過程可表示為:U8 = [(byte)(0xE0 | (0x0F & (U>>12))),(byte)(0x80 | (0x03F & (U>>6)),(byte)(0x80 | (0x3F & U)]。
          ?
          ????? UTF-16編碼在Unicode基礎上進行了一些細節上的擴充,增加了對Unicode編碼沒有包括的字符的表示方式。UTF-16對Unicode的擴充并沒有影響Unicode編碼中的原有字符,容易看出Unicode是UTF-16的子集。Unicode編碼將0xD800-0xDFFF區間的數值保留,被稱為代理區間,區間共包含2048個數值,其中0xD800-0xD6FF是高半代理區,0xDC00-0xDFFF是低半代理區。UTF-16編碼就是在Unicode編碼基礎上利用代理區擴充字符編碼的機制。UTF-16編碼從兩個區域分別取一個編碼,組成一個4字節的代理對來表示一個編碼字符,就能夠在Unicode基礎上擴充了1024*1024個字符。UTF-16足夠用來編碼全球的所有字符,微軟從Windows2000開始支持UTF-16編碼。
          ?
          關于Little-Endian和Big-Endian
          ????? 在不同體系的計算機系統中,編碼的Unicode字符在內存中存儲的順序是不同的。使用Inter生產的CPU的計算機,內存中數據存儲通常是低字節在前,高字節在后,這種存儲方式被稱為Little-Endian。在對于一些計算機,內存中數據存儲通常是高字節在前,低字節在后,這種存儲方式被稱為Big-Endian。
          ????? UTF-16編碼的文件通常在文件開頭用字符標志出使用的存儲方式:若文件開頭是“0xFF 0xFF”,表示文件其余部分是Little-Endian的 UTF-16編碼;若文件開頭是“0xFE 0xFF”,表示文件其余部分是Big-Endian的 UTF-16編碼。

          posted @ 2006-09-28 11:36 xyang 閱讀(666) | 評論 (0)編輯 收藏

          [概述]
          ????? 在Windows操作系統中使用記事本新建一個文本文件,在文件里面寫入“聯通”兩個字并保存。當再次打開這個文本文件時候,在記事本中看到得卻不是剛剛輸入的“聯通”,而是亂碼。網絡上有人把這個奇怪現象包裝成把戲,如果你曾遇到過這種把戲就會知道,他們往往讓你建立兩個文本文件進行對比,其中一個輸入“聯通”,另外一個可能是“移動”等等,最后試圖八卦地讓你相信聯通、移動和微軟之間有著種種恩怨情仇。

          [解釋]
          ????? 這是一個字符編碼應用的奇怪現象,講的明白點,可以說是記事本開小差了!記事本為什么會犯錯誤?記事本犯了怎樣的錯誤呢?也許你會迫不及待的想知道這些問題,如果是這樣,我不會讓你空腹而歸的。
          ????? 在簡體中文操作系統中默認的本地字符集編碼是GBK編碼,除非你在保存記事本文本文件時候選擇了其他編碼方式,否則用記事本錄入的字符信息將使用GBK編碼進行儲存。巧合的是,“聯通”這兩個字符的GBK編碼具有UTF-8編碼的特征,記事本犯下的錯誤正是將GBK編碼存放的記錄有“聯通”兩個字符的文件誤認為UTF-8編碼的文件。或許你會問,UTF-8編碼的文件不是以“EF BB BF”三個特殊字節開頭嗎?既然這樣,記事本怎么會犯這么低級的錯誤呢?沒錯,UTF-8編碼規定使用UTF-8編碼的文件以“EF BB BF”三個特殊字節開頭,但并不是強制性要求,早期的UTF-8編碼文件就不遵循這個規定。因此記事本不能依靠文件的開頭字節判斷一個文件是否是UTF-8編碼,而只能對文件中的數據進行簡單的編碼分析來確定。正是這個原因,才有了字符編碼應用中的這個奇怪又無法避免的現象。

          [細節]
          ????? 如果上面的解釋對于你來說只是杯開胃紅酒,那我還是塊點把主食呈上吧,一份大峽谷香烤豬肋排。UTF-8編碼采用1-3個字節對字符進行編碼,編碼字節數與字符的Unicode編碼值有嚴格的對應關系,讓我們回憶下UTF-8編碼和Unicode的對應關系吧。

          ????? Unicode編碼值???????????????????????????? ?UTF-8編碼結構
          ????? \u0001 - \u007E?????????????????????????? 0XXXXXXX
          ????? \u0080 - \u07FF 和 \u0000?????????? ?110XXXXX 10XXXXXX
          ????? \u0800 - \uFFFF??????????????????????????? 1110XXXX 10XXXXXX 10XXXXXX

          ????? “聯通”這兩個字符的GBK編碼值是“C1 AA CD A8",GBK編碼方式使用兩個字節對一個字符進行編碼,因此以GBK編碼方式存放的錄有“聯通”兩個字符的文件的大小為四個字節。接下來分別觀察“聯通”這兩個字符GBK編碼值的二進制形式,你有發現有趣的事。

          ????? 聯??? GBK??? 十六進制:C1 AA??? 二進制:1100 0001,1010 1010
          ????? 通??? GBK??? 十六進制:C1 AA??? 二進制:1100 1101,1010 1000

          ????? 請注意上面二進制數據的著色部分,你想到了什么?對,它們和UTF-8編碼結構中的補充位完全一致,UTF-8編碼的補充位使得編碼值更有規律,而記事本剛好憑借這個特征區分UTF-8編碼的文件。存有“聯通”兩個字符的文件的所有數據都符合這個特征,就是這樣,記事本徹底的將文件誤認為UTF-8編碼的文件。
          ????? 將錯就錯,讓我們來看看這個錯誤是怎樣收場的。如果把“聯通”的GBK編碼值當作UTF-8編碼值,那文件就成為一個寫有數據“C1 AA CD A8”并以UTF-8編碼的文件,當使用記事本再次打開的時候會看到什么呢?只要將UTF-8編碼轉換成Unicode編碼就知道了。UTF-8編碼“C1 AA CD A8”轉換成Unicode編碼后,編碼值為“6A 00 68 03”(轉換方法請參考本Blog中的《字符編碼》一文)。0x006A這個Unicode編碼值位于\u0001 - \u007E之間,若要轉換為UTF-8編碼,顯然只能用一個字節進行編碼,因此“聯”的GBK編碼“C1 AA”雖然特征上貌似UTF-8編碼,但它卻不對應任何一個UTF-8編碼。接著看0x0368這個Unicode編碼值,這個值對應了字符“?”,這也正是我們將在記事本中看到的內容。或許你會說我看到的是一個黑色矩形啊,這只是字體的原因,你將字體改為宋體或者其他字體,看到的就是字符“?”。
          ????? 對于中文字符,UTF-8編碼要用三個字節進行編碼,因此,如果你使用記事本錄入“聯通”,然后選擇以UTF-8編碼方式保存的話,文件大小應為9個字節(包含三個字節的開頭數據),而同樣的文件GBK編碼卻是4個字節。最后附上“聯通”的GBK、UTF-8、Unicode編碼值,以及記事本的錯誤思維。

          ????? 聯通??GBK? C1 AA CD A8??? UTF-8? E8 81 94 E9 80 9A??? Unicode? 54 80 1A 90
          ????? 聯通? GBK? C1 AA CD A8??? UTF-8? C1 AA CD A8????????????Unicode? 6A 00 68 03? (將GBK值誤認為UTF-8值的結果)

          posted @ 2006-09-28 11:36 xyang 閱讀(305) | 評論 (0)編輯 收藏

          [概述]
          ????? 在編程中字符編碼絕對是個值得重視的問題,當讀取一個文件或是得到一個輸入流,你需要分析數據的編碼方式、形態,以便能正確的處理、顯示數據所表示的字符。

          [細節]
          ????? 1)? 在簡體中文操作系統中,從鍵盤輸入的原始字符采用的是GBK編碼方式,對應到其他操作系統,采用的應是系統默認的本地字符集。而在程序設計語言中,字符和字符串則通常是使用Unicode編碼方式,這一點可以用下列代碼說明(使用Java語言描述)。

          ????? int ch = System.in.read(); //從鍵盤輸入中讀取一個字節的數據
          ????? 如果輸入“中國”兩個字符,使用上面的代碼將所有的數據讀取,將得到“D6 D0 B9 FA”,這寫數據正是“中國”兩個字符的GBK編碼值。
          ????? String tmp = "中國"; //定義字符串并賦值
          ????? for(int i=0;i<tmp.length();i++)
          ????? {
          ????? //將字符串中的每個字符編碼值以十六進制形式顯示
          ???????? System.out.println(Integer.toHexString(ch));
          ????? }

          ????? 上面代碼最后顯示的內容是“4E2D 56FD”,而這正是“中國”兩個字符的Unicode編碼值。
          ?
          ????? 2) 不僅是輸入的原始字符采用GBK編碼,屏幕輸出的最終數據也要采用GBK編碼,下面的代碼能說明問題。

          ????? String tmp = "中國"; //定義字符串并賦值
          ????? System.out.println(tmp); //將字符串tmp輸出到顯示屏

          ????? 代碼運行后,在顯示屏上顯然能看到“中國”兩個字符,而字符串tmp分明是采用Unicode進行編碼的,是不是剛才提出的命題站不住腳呢?其實,在調用println()方法后,該方法自動的將字符串tmp的編碼方式從Unicode轉換成了本地編碼GBK,這樣才能在屏幕上正常的顯示中文。如果你仍然懷疑,請繼續往下看。

          ????? byte [] buf1 = tmp.getBytes("Unicode"); //將字符串tmp以Unicode編碼方式儲存在字節數組中
          ????? byte [] buf2 = tmp.getBytes("GB2312"); //將字符串tmp以UGBK編碼方式儲存在字節數組中
          ????? //在屏幕輸出流中直接寫字節數組
          ????? System.out.write(buf1);
          ????? System.out.write(buf2);

          ????? 這樣的作法將會得到什么結果呢?結果也許會令你感到驚訝,buf1的數據輸出后顯示為亂碼,而buf2的數據輸出后赫然顯示為“中國”兩個字符。可以把命題說得明確點:如果要在屏幕上輸出漢字,那么字符的最終編碼方式必須是GBK編碼方式。對于數字和英文字母,以及ASCII編碼集中包含的符號,字符的最終編碼方式可以是ASCII,這種情況下如果使用Unicode編碼,那么顯示的結果會是這樣“1 2 3 a b c ”,本來想顯示的內容是“123abc”。顯示結果字符間多了個貌似空格的字符,這是因為ASCII編碼使用一個字節,Unicode編碼使用兩個字節,在ASCII編碼轉換為Unicode時候,只是單純地在編碼值前面補充一個全為0的字節,這個字節在最終顯示的時候被看做是空字符NUL。
          ?
          ????? 3) 在涉及網頁、網絡流和關系數據庫方面編程的時候,字符編碼總喜歡戲弄編程人員,不花心思去馴服它的結果將是得到一堆亂碼。例如在讀取數據數據時候,數據庫中的內容是中文字符,如果數據庫沒有考慮到中文支持問題就很容易得到亂碼。再例如程序運行的平臺默認編碼并非GBK,在獲取GBK編碼的字符數據時候,程序會將數據看作默認編碼,這樣也容易產生亂碼。在上述情況中編寫程序的時候,就應該耐心的分析數據的編碼方式,合理的編寫代碼防止亂碼。
          ?
          [例子]???
          ????? 記得在《Java手機程序設計入門與應用》(王森 編著)一書的第13章-MIDP網絡程序設計中有一段使用HTTP進行網絡連接的實例代碼,部分代碼如下所示。

          ????? String url = " http://127.0.0.1/test.html ";
          ????? HttpConnection hc = (HttpConnection)Connector.open(url);
          ????? DataInputStream dis = new DataInputStream(hc.openInputStream());
          ????? String content = "";
          ????? int ic;
          ????? while((ic = dis.read()) != -1)
          ????? {
          ????????? content += (char)ic;
          ????? }
          ????? Form f = new Form("HTTP Test");
          ????? f.append(content);
          ????? Display.getDisplay(this).setCurrent(f);

          ????? 這段代碼讓手機通過HTTP協議與網絡中的主機進行通信,然后獲得網絡主機上的文件test.html并將文件內容讀取到字符串變量中,最后顯示到程序窗體中。如果程序這般執行的話,你會發現MIDlet顯示出來中文都是亂碼。作者稱“之所以會有這種結果,原因在于我們的仿真器支持Unicode的緣故。”,作者的意思似乎是MIDlet將本地編碼的字符數據誤認為了Unicode編碼的數據,因此不能正常顯示,然后推薦了一種解決方法:使用ASCII形態的Unicode。
          ????? 所謂ASCII形態的Unicode指的是使用ASCII編碼的字符來表示Unicode編碼值,反過來說就是將Unicode的編碼值看做字符,再用ASCII對這些字符進行編碼存放。比如“中國”這兩個字符的ASCII形態的Unicode編碼字符為“\u4e2d\u56fd”,0x4E2D 0x56FD 分別為“中”和“國”的Unicode編碼值,將編碼值作為字符,然后在前面添加“\u”標識符,以便進行還原。再對這些字符進行ASCII編碼就得到了ASCII形態的Unicode編碼值,最終的值為“5C 75 34 65 32 64 5C 75 35 36 66 64”,一共12個字節的數據,分別對應了“\u4e2d\u56fd”中的一個字符。使用jdk*\bin文件夾下的native2ascii.exe程序可以很方便的將一個文件轉換為ASCII形態的Unicode編碼。將文件test.html轉換形態后,MIDlet中需要再次將ASCII形態的Unicode轉換為Unicode編碼,這個轉換方法需要自己寫,最后MIDlet中顯示出來的就是正常的中文字符。

          ????? 在我看來,那本書的作者沒有把握住問題的真正原因,也或許是我們使用的模擬器和平臺不同。如果把握住真正的原因,問題的解決方法就變得很簡單了。前面說過,要在屏幕上顯示出中文,字符的最終編碼形式必須是GBK,在中國大陸發現的手機都能顯示中文,也就說明手機中都支持GBK編碼。那為什么會出現中文字符亂碼的問題呢?我的理由是手機中采用的默認編碼是ISO8859-1,對于從網絡中讀入的字符數據,在沒有指明的情況下,MIDlet一律將它們看作是ISO8859-1編碼的數據。而test.html的編碼方式是GBK,MIDlet犯了個錯誤,它將GBK編碼的數據誤認為了ISO8859-1編碼的數據,然后在顯示的時候又進行了一次ISO8859-1到GBK的編碼轉換,這樣的結果是數據遭到了破壞,顯示出來的中文也就變成了亂碼。
          ????? 把握住了原因,解決起來就十分方便了。既然MIDlet將GBK編碼的數據誤認為ISO8859-1編碼的數據,那么我們只要在程序中指明數據的編碼方式就可以了,而不用使用“ASCII形態的Unicode”這樣的舍本求末的方法。下面是解決MIDlet網絡連接中文亂碼問題的代碼,這些代碼將證明我的觀點。

          ????? http://127.0.0.1/test.html;
          ????? HttpConnection hc = (HttpConnection)Connector.open(url);
          ??????byte [] buf = new byte[1024];
          ????? int len = hc.openInputStream().read(buf);? //讀取網絡數據
          ????? String content = new String(buf,0,len,"GB2312");? //指定數據為GBK編碼
          ??????Form f = new Form("HTTP Test");
          ????? f.append(content);?
          ????? display.setCurrent(f);

          ????? 上述代碼中關鍵的一句是:
          ????? String content = new String(buf,0,len,"GB2312");
          ????? 這句代碼告訴MIDlet從網絡中讀取的數據使用的是GBK編碼方式,然后MIDlet便能爭取處理和顯示這些數據。
          ????? 如果將這句代碼改寫為:?
          ????? String content = new String(buf,0,len);
          ????? 或者是:
          ??????String content = new String(buf,0,len,"ISO8859-1");
          ????? 都將出現同樣的中文亂碼現象,由此斷定錯誤的原因是手機默認編碼使用ISO8859-1,MIDlet將從網絡中讀取的GBK編碼的數據誤認成了ISO8859-1編碼的數據。

          posted @ 2006-09-28 11:35 xyang 閱讀(680) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 东乡| 淮滨县| 亚东县| 周宁县| 上高县| 青岛市| 元朗区| 曲沃县| 涞源县| 遵义县| 拜城县| 苏尼特左旗| 紫云| 泉州市| 巩义市| 万安县| 新蔡县| 赣州市| 阜新市| 辛集市| 甘谷县| 古蔺县| 惠东县| 高淳县| 合阳县| 封丘县| 鞍山市| 嘉黎县| 武义县| 尼木县| 循化| 光泽县| 岢岚县| 江津市| 通渭县| 德令哈市| 宝山区| 东莞市| 砚山县| 泰宁县| 景德镇市|