2014年4月5日 星期六

Java 複習筆記 : 字串 (續)

Java 常用函式庫改寫得差不多了, 找了一下 PHP 與 Python 的書, 看看還有哪些函式是值得移植到 Java 的. 以下是字串處理時可能會用到的幾個好用的函式 :

# Java 複習筆記 : 字串 (前一篇)

1. nl2br() :

此函式來自 PHP, 用來將 text 檔的換行符號 (Windows 是 "\r\n" 或 "%0D%0A") 改為 HTML 的換行標籤 <br>, 這在多行純文字內容改成網頁格式上挺常用的, 特別是在寫 JSP 或 Servlet 時常用. 參見 :

# PHP 字串函式庫
# http://php5.idv.tw/documents/mou/string/nl2br.html

依據 PHP 的文件說明, 此函式會在字串中所有的 newline 字元前面插入 <BR> 後傳回字串. 這裡為求簡化, 直接把換行字元替換掉. 但換行字元因作業系統而異, Windows 是 "\r\n", 而 Linux 是 "/n", 若寫死的話就有跨平台問題, 必須利用 System.getProperty("line.separator") 來取得系統之分行字元為妥, 範例如下 :

public class mytest {
  public static void main(String[] args) {
    System.out.println(nl2br("0\n1\n2\n3\n4"));  
    System.out.println(nl2br("0\r\n1\r\n2\r\n3\r\n4"));
    }
  public static String nl2br(String str) {
    String nl=System.getProperty("line.separator");
    return str.replaceAll(nl,"<br>");
    }
  }

執行結果 :

0
1
2
3
4
0<br>1<br>2<br>3<br>4

這是在 Windows 上的輸出, 第一次呼叫 nl2br() 的字串是以 "\n", 在 Windows 上執行 getProperty("line.separator") 傳回的是 "\r\n", 因此都不匹配, 沒有轉換成功; 第二次呼叫用 "\r\n" 分行就匹配了.


# 換行的另類寫法

2. quotemeta() :

此函式來自 PHP, 功能是將下列特殊字元 (即正規表示法之特殊字元) 加上反斜線 (用來脫逸) :

. \\ + * ? [ ^ ] ( $ )

範例如下 :

public class mytest {
  public static void main(String[] args) {
    System.out.println(quotemeta("1(2)3.+4*"));  //輸出 1\(2\)3\.\+4\*
    }
  public static String quotemeta(String str) {
    String nl=System.getProperty("line.separator");
    return str.replaceAll("([^a-zA-z0-9])","\\\\$1");
    }
  }

3. chr() 與 ord() :

此兩函式來自 PHP, chr() 是傳入一個整數, 傳回其 ASCII 字元; 而 ord() 則是相反, 傳入字元, 傳回其 ASCII 碼 (整數). 這在 Java 只要用型態轉型即可 :

public class mytest {
  public static void main(String[] args) {
    System.out.println(ord('A'));  //輸出 65
    System.out.println(chr(65));   //輸出 'A'
    }
  public static int ord(char ch) {
    return (int)ch;
    }
  public static char chr(int i) {
    return (char)i;
    }
  }

4. ljust() 與 rjust() :

這兩個好用的方法來自 Python, API 詳見 :

# Python String rjust() Method
# Python String ljust() Method

ljust() 是用來在字串前面填充指定字元, 使其總字串長度正規化為指定長度, 而 rjust() 則是在字串後面填充, 此二方法在調整字串輸出為向左或向右對齊時很有用. 例如一個二維陣列 :

    String[][] users={{"Id","Name","Gender","Age","Email"},
                               {"1","Amy","Female","12","amy@gmail.com"},
                               {"2","Peter","Male","14","peter@gmail.com"},
                               {"3","Kelly","Female","16","kelly@gmail.com"}};

如果直接列印的話, 用 tab 隔開就會很整齊, 例如下面的範例  :

public class mytest {
  public static void main(String[] args) {
    String[][] users={{"Id","Name","Gender","Age","Email"},
                              {"1","Amy","Female","12","amy@gmail.com"},
                              {"2","Peter","Male","14","peter@gmail.com"},
                              {"3","Kelly","Female","16","kelly@gmail.com"}};
    for (int i=0; i<users.length; i++){
      for (int j=0; j<users[i].length; j++){
        System.out.print(users[i][j] + "\t");
        }
      System.out.println("");
      }
    }
  }

執行結果 :


似乎 \t 就搞定了, 但是那是因為我們把最長的字串 Email 放在最後面的緣故, 如果 Email 後面還有欄位, 那麼就會無法對齊了, 例如在 Email 後面再加上 Tel 欄位 :

public class mytest {
  public static void main(String[] args) {
    String[][] users={{"Id","Name","Gender","Age","Email","Tel"},
                               {"1","Amy","Female","12","amy@gmail.com","123"},
                               {"2","Peter","Male","14","peter@gmail.com","456"},
                               {"3","Kelly","Female","16","kelly@gmail.com","789"}};
    for (int i=0; i<users.length; i++){
      for (int j=0; j<users[i].length; j++){
        System.out.print(users[i][j] + "\t");
        }
      System.out.println("");
      }
    }
  }



可見 Tel 標題與其內容沒有對齊, 這是因為 \t 長度是 8 個空格的緣故, 當內容大於 8 個字元時, 它會空一格往後推. 為了解決這種對齊問題, 雖然可以使用兩個 tab (\t\t) 保留 16 個字元空間, 但是 \t 均為向左對齊, 無法向右對齊, 而且一個 tab 單位為 8 格, 缺乏彈性. 解決之道是用 ljust() 或 rjust() 調整每個欄位寬度 :

public class mytest {
  public static void main(String[] args) {
    String[][] users={{"Id","Name","Gender","Age","Email","Tel"},
                               {"1","Amy","Female","12","amy@gmail.com","123"},
                               {"2","Peter","Male","14","peter@gmail.com","456789"},
                               {"3","Kelly","Female","16","kelly@gmail.com","123456789"}};
    for (int i=0; i<users.length; i++){
      for (int j=0; j<users[i].length; j++){
        if (j==4) {System.out.print(ljust(users[i][j],20));}
        else if (j==5) {System.out.print(ljust(users[i][j],10));}
        else {System.out.print(rjust(users[i][j],6));}
        }
      System.out.println("");
      }
    }
  public static String ljust(String str, int width) {
    return ljust(str, width, ' ');
    }
  public static String ljust(String str, int width, char fill) {
    int len=str.length();
    if (width <= len || width < 0) {return str;}
    else {
      StringBuilder sb=new StringBuilder();
      for (int i=0; i<width-len; i++) {sb.append(fill);}
      sb.append(str);
      return sb.toString();
      }
    }
  public static String rjust(String str, int width) {
    return rjust(str, width, ' ');
    }
  public static String rjust(String str, int width, char fill) {
    int len=str.length();
    if (width <= len || width < 0) {return str;}
    else {
      StringBuilder sb=new StringBuilder(str);
      for (int i=0; i<width-len; i++) {sb.append(fill);}
      return sb.toString();
      }
    }
  }

可見 Email 與 Tel 欄位利用 ljust() 在左方填充空格達成向右對齊目的, 並分別固定占用 20 格與 10 格; 其餘欄位用 rjust() 在右方填充空格達成向左對齊目的.

5. bin2hex() 與 hex2bin() :

此兩函式來自 PHP, bin2hex() 用來將二進位整數轉成 16 進位數, 而 hex2bin() 則反過來將 16 進位轉成二進位.

http://www.360doc.com/content/12/0913/14/203871_235898869.shtml



~未完待續~

參考 :

# http://stackoverflow.com/questions/6318710/javascript-equivalent-of-perls-q-e-or-quotemeta
# How to escape text for regular expression in Java
# Perl to Java regular expressions tutorial
# is Java 10x more verbose than Python (LOC)?

沒有留言 :