當柳上原的風吹向天際的時候...

          真正的快樂來源于創造

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks
          編程中有時需要將一段文本分解成標記,比如說14+2*3需要變成14,+,2,*,3的樣式,再比如說select a from b,需要變成select,a,from,b的形式,要寫出這樣的代碼不難,考慮到通用性,于是我制作了下面這個通用類,用戶只需要指定合法字符和分隔字符的正則表達式,程序即能將字符串分解成標記并注明類型,下面是源碼:

          1.用于表示標記的Token類,含有文本和類型兩個屬性:
          package com.heyang.tokenmaker;

          /**
           * 標記類,內含文本及類型
           * 說明:
           * 作者:heyang(heyang78@gmail.com)
           
          */
          public class Token{
              
          // 有效內容類型
              public static final String Type_Content="Content";
              
              
          // 分隔符類型
              public static final String Type_Separator="Seperator";
              
              
          // 標記文本
              private String text;
              
              
          // 標記類型
              private String type;
              
              
          /**
               * 構造函數
               * 
          @param text
               * 
          @param type
               
          */
              
          public Token(String text,String type){
                  
          this.text=text;
                  
                  
          if(type.equals(Type_Content) || type.equals(Type_Separator)){
                      
          this.type=type;
                  }
                  
          else{
                      
          throw new IllegalArgumentException(type+"不是有效的類型。");
                  }
                  
              }

              
          public String getText() {
                  
          return text;
              }

              
          public String getType() {
                  
          return type;
              }
          }

          2.用于分解的TokenMaker類:
          package com.heyang.tokenmaker;

          import java.util.ArrayList;
          import java.util.List;
          import java.util.regex.Matcher;
          import java.util.regex.Pattern;

          import org.apache.commons.lang.StringUtils;

          /**
           * 傳入一個字符串,將它轉化為記號放在鏈表中
           * 說明:
           * 作者:何楊(heyang78@gmail.com)
           
          */
          public class TokenMaker{
              
          // 來源字符串
              private String sourceString;
              
              
          // 用正則表達式表示的,表示單個有效字符的字符串,注意這個是表示合法單字字符的正則表達式
              private String validPatten;
              
              
          // 用正則表達式表示的,表示單個分隔符的字符串,注意這個是表示合法單字字符的正則表達式
              private String separatorPattern;
              
              
          // 記號鏈表
              private List<Token> tokens;
              
              
          /**
               * 構造函數
               * 
          @param sourceString
               * 
          @param validPatten
               * 
          @param seperatorPattern
               * 
          @throws Exception
               
          */
              
          public TokenMaker(String sourceString,String validPatten,String seperatorPattern) throws Exception{
                  
          this.sourceString=sourceString;
                  
          this.validPatten=validPatten;
                  
          this.separatorPattern=seperatorPattern;
                  
                  findTokens(sourceString);
              }
              
              
          /**
               * 找到指定的標記并放入鏈表中
               * 
               * 說明:
               * 
          @param sourceString
               * 
          @throws Exception
               
          */
              
          private void findTokens(String sourceString)throws Exception{
                  tokens
          =new ArrayList<Token>();
                  
                  sourceString
          =sourceString.toString();
                  
          final String End = "~";// 結束標志,這個地方注意與有效文本差別化
                  sourceString+=End;// 加上結束標志
                  
                  
          // 單詞,用來累加字符
                  String word = "";
                  
                  
          for (int i = 0; i < sourceString.length(); i++) {
                      
          // 取得每個字符
                      String str = String.valueOf(sourceString.charAt(i));
                      
                      
          if(End.equals(str)){
                          
          // 將word放入鏈表
                          addTokenToList(new Token(word,Token.Type_Content));
                          
          break;
                      }
                      
                      
          // 字符的驗證
                      if(isValid(str)==false){
                          
          throw new Exception(""+this.sourceString+"找到非法的字符'"+str+"',無法進行求值.");
                      }

                      
          // 判斷是否空格
                      if (StringUtils.isBlank(str)) {
                          
          if (word.trim().length() < 1) {
                              
          // 碰到空格而word中沒有字符則從頭再來
                              continue;
                          } 
          else {
                              
          // 將word放入鏈表
                              addTokenToList(new Token(word,Token.Type_Content));

                              
          // 然后吧word置空后繼續累加
                              word = "";
                          }
                      } 
                      
          else if(isSeparator(str)){
                          
          // 將word放入鏈表
                          addTokenToList(new Token(word,Token.Type_Content));
                          
                          
          // 將符號放入鏈表
                          addTokenToList(new Token(str,Token.Type_Separator));

                          
          // 然后吧word置空后繼續累加
                          word = "";
                      }
                      
          else {
                          
          // 不是則繼續累加
                          StringBuilder sb=new StringBuilder(word);
                          sb.append(str);
                          word
          =sb.toString();
                          
                          
          //word += str;
                      }
                  }
              }
              
              
          /**
               * 將標記添加到標記鏈表
               * 
               * 
          @param token
               
          */
              
          private void addTokenToList(Token token){
                  
          if(token.getText().trim().length()>0){
                      tokens.add(token);
                  }
              }
              
              
          /**
               * 打印鏈表中的標記
               * 
               
          */
              
          public void printTokens(){
                  System.out.println(
          "\n將文字"+sourceString+"轉化后的標記為:");
                  System.out.println(
          "序號\t內容\t類型");
                  System.out.println(
          "-------------------------");
                  
                  
          int index=1;
                  
                  
          for(Token token:tokens){
                      System.out.println((index
          ++)+"\t"+token.getText()+"\t"+token.getType());
                  }
              }
              
              
          /**
               * 判斷是否有效字符
               * 
               * 說明:
               * 
          @param str
               * 
          @return
               
          */
              
          private boolean isValid(String str){
                  Pattern p 
          = Pattern.compile(validPatten,Pattern.CASE_INSENSITIVE);
                  Matcher m 
          = p.matcher(str);
                  
          return m.find();
              }
              
              
          /**
               * 判斷是否分隔符
               * 
               * 說明:
               * 
          @param str
               * 
          @return
               
          */
              
          private boolean isSeparator(String str) {
                  Pattern p 
          = Pattern.compile(separatorPattern,Pattern.CASE_INSENSITIVE);
                  Matcher m 
          = p.matcher(str);
                  
          return m.find();
              }
              
              
          /**
               * 取得標記鏈表
               * 
               * 說明:
               * 
          @return
               * 創建時間:2010-6-27 上午12:46:47
               * 修改時間:2010-6-27 上午12:46:47
               
          */
              
          public List<Token> getTokens() {
                  
          return tokens;
              }
              
              
          /**
               * 取得標記的內容鏈表
               * 
               * 說明:
               * 
          @return
               * 創建時間:2010-6-27 上午08:59:34
               * 修改時間:2010-6-27 上午08:59:34
               
          */
              
          public List<String> getTokenConcents(){
                  List
          <String> ls=new ArrayList<String>();
                  
                  
          for(Token token:tokens){
                      ls.add(token.getText());
                  }
                  
                  
          return ls;
              }
              
              
          /**
               * 測試
               * 
               * 說明:
               * 
          @param args
               * 
          @throws Exception
               * 創建時間:2010-6-27 上午09:00:02
               * 修改時間:2010-6-27 上午09:00:02
               
          */
              
          public static void main(String[] args)  throws Exception{
                  
          new TokenMaker("96.2+8*5-12*(4-1)/2^(3%10)","[0-9\\.+-[*]/()\\^\\%]","[+-[*]/()\\^\\%]").printTokens();
                  
          new TokenMaker("select A a,b, v from ta,tb where 1=1 and 2=2 order by a asc","[\\w=<>!\\s,]","[\\s,]").printTokens();
              }
          }

          3.對算式和Sql語句分解的結果:

          將文字96.
          2+8*5-12*(4-1)/2^(3%10)轉化后的標記為:
          序號    內容    類型
          -------------------------
          1    96.2    Content
          2    +    Seperator
          3    8    Content
          4    *    Seperator
          5    5    Content
          6    -    Seperator
          7    12    Content
          8    *    Seperator
          9    (    Seperator
          10    4    Content
          11    -    Seperator
          12    1    Content
          13    )    Seperator
          14    /    Seperator
          15    2    Content
          16    ^    Seperator
          17    (    Seperator
          18    3    Content
          19    %    Seperator
          20    10    Content
          21    )    Seperator

          將文字select A a,b, v from ta,tb where 
          1=1 and 2=2 order by a asc轉化后的標記為:
          序號    內容    類型
          -------------------------
          1    select    Content
          2    A    Content
          3    a    Content
          4    ,    Seperator
          5    b    Content
          6    ,    Seperator
          7    v    Content
          8    from    Content
          9    ta    Content
          10    ,    Seperator
          11    tb    Content
          12    where    Content
          13    1=1    Content
          14    and    Content
          15    2=2    Content
          16    order    Content
          17    by    Content
          18    a    Content
          19    asc    Content

          posted on 2010-06-27 09:34 何楊 閱讀(1412) 評論(1)  編輯  收藏

          Feedback

          # re: 將字符串分解成標記的類[未登錄] 2010-06-27 20:34 feenn
          敢于嘗試很好,其實最通用的是詞法解析工具。可以看看JFlex  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 班戈县| 安乡县| 临澧县| 遂昌县| 宝山区| 舒兰市| 股票| 和平县| 冀州市| 广饶县| 安顺市| 宝鸡市| 聂荣县| 甘谷县| 冀州市| 霍林郭勒市| 大同市| 清苑县| 城步| 保山市| 信宜市| 稷山县| 法库县| 大厂| 正阳县| 吴江市| 彭阳县| 连江县| 江孜县| 彰武县| 龙陵县| 泊头市| 柘城县| 黑龙江省| 广河县| 赣州市| 黄冈市| 宕昌县| 沙湾县| 南皮县| 格尔木市|