1.5.5. ChoiceFormat的pattern構造方法... 4
在Java中,有java.text.Format,java.util.Formatter,java.util.regex.Pattern三個格式化相關的體系,使用起來較爲複雜,在這裏總結一下。
1.1. Format的方法
java.text.Format做爲一個抽象類,有二個抽象方法,
format(Object obj, StringBuffer toAppendTo,FieldPosition pos):格式化一個對象,並將得到的文本追加到給定的字符緩衝區。是將obj格式化爲字符串,並加入到toAppendTo中。
parseObject(String source, ParsePosition pos): 分析字符串文本,生成一個對象。是format方法的逆向方法,將String轉化爲Object。
另外的format和parseObject這兩個方法的重載。
方法formatToCharacterIterator(Objectobj)並非抽象方法,api上要求子類必須實現這個方法。
1.2. Format的子類
Java 2 平臺爲格式化日期、消息和數字分別提供了三個特殊的 Format 的子類:DateFormat(抽象類)、MessageFormat和 NumberFormat(抽象類)。
——>DateFormat ——>SimpleDateFormat
Format ——>MessageFormat
——>NumberFormat——>ChoiceFormat
——> DecimalFormat用於格式化十進制數字
DateFormat 是日期/時間格式化子類的抽象類, 有一些static的get***Instance()方法來獲得實例。通過設置結果的長度和地區,來獲得日期,時間等的格式formatter。不太常用。
一般會使用SimpleDateFormat子類,newSimpleDateFormat("yyyy-MM-dd")或newSimpleDateFormat("yyyy-MM-dd HH:mm:ss"),來獲得常用的時間格式。DateFormat 的get***Instance()方法一般也是獲得SimpleDateFormat。
看DateFormat的源代碼有個疑問,如果繼承了DateFormat類,那DateFormat. get***Instance()的方法還是返回SimpleDateFormat? DateFormat.get是私有的,也不能覆蓋。
DateFormat類中還有一些static的字段,如WEEK_OF_MONTH_FIELD,WEEK_OF_YEAR_FIELD。api上說在FieldPosition中使用,用於對齊。
java.util.Calendar也是日期操作相關的類,實現類爲GregorianCalendar。主要對日期進行操作。注意add方法和roll方法的區別,roll方法不更改更大的字段。還有一些靜態的變量DAY_OF_MONTH,DAY_OF_WEEK等,在get
/set/
add/roll方法中使用。
和SimpleDateFormat一樣,也需要傳入一個pattern。如
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet{0,number,integer}.",
7,new Date(), “ a message ”);
其中
{1,time}中1是指第幾個參數,time是指格式化的類型。根據api進行設置,是調用NumberFormat和DateFormat進行格式化的。
還可以調用parse方法將字符串轉化爲Obejct。
NumberFormat 是所有數字格式的抽象基類。類結構與DateFormat類似。主要也是通過get***Instance方法獲得實現類DecimalFormat。
比較常用的方法有:
setParseIntegerOnly:隻影響分析。設爲true,則忽略小數點以後的位置。
setDecimalSeparatorAlwaysShown:隻影響格式化,且隻影響小數點後沒有數字的情況?設置分組符號是否顯示。例如1,234中的,號是否顯示。
setGroupingUsed
:是否分組。如果此格式中使用了組,則返回 true。例如,在英國語言環境中,如果設置了組,則數 1234567 可能被格式化爲 "1,234,567"。
還可以設置小數/整數部分的最大/小位數。
關於parse方法中的ParsePosition和 format方法中的FieldPosition待研究。
1.5.2.
子類DecimalFormat
DecimalFormat 是NumberFormat 的一個具體子類,用於格式化十進制數字。在DecimalFormat中傳入pattern,可以自定義格式化類型。舍入方式是half-even(四捨五入)。
DecimalFormat 模式包含正數和負數子模式,例如 "#,##0.00;-#,##0.00"。;後面的代表負數模式。單獨的 "0.00"等效於 "0.00;-0.00"。如果存在顯式的負數子模式,則它僅指定負數前綴和後綴;
0:代表是數字;如果不存在則顯示爲0;
#:代表是數字;
,:分組分隔符;沒有則不分組
1.5.3. 子類ChoiceFormat
ChoiceFormat通常用於在MessageFormat 中處理複數。創建 ChoiceFormat 時,可以指定一個 format 數組和一個limit 數組。這些數組的長度必須相同。
如api中用於轉換星期的例子
double[] limits = {1,2,3,4,5,6,7};
String[] monthNames ={"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
ChoiceFormat form = new ChoiceFormat(limits,monthNames);
ParsePosition status = new ParsePosition(0);
for (double i = 0.0; i <= 8.0; ++i) {
status.setIndex(0);
System.out.println(i + " -> "+ form.format(i) + " -> "
+form.parse(form.format(i),status));
}
form.format(i)根據limits的數字轉換爲星期幾的名稱。limits中的數字必須按升序排列,如果提供的數字不在limits中,則選擇使用第一個或最後一個索引。
form.parse(form.format(i),status),則根據Name轉換爲limits中的值。
下面是ChoiceFormat的api中一個較複雜的帶模式格式的例子, 和MessageFormat一起使用:
//生成ChoiceFormat
double[] filelimits = {0,1,2};
String[] filepart = {"are nofiles","is one file","are {2} files"};//這裏的2是指從testArgs中取第二個元素的值
ChoiceFormat fileform = newChoiceFormat(filelimits, filepart);
//定義Format數組testFormats,分別爲ChoiceFormat,null,NumberFormat
//ChoiceFormat用於{0}, null用於{1},NumberFormat用於{2}
Format[] testFormats = {fileform, null,NumberFormat.getInstance()};
//將MessageFormat的formats設爲testFormats
//testFormats中的格式順序對應於模式字符串中的格式元素的順序
//最好使用setFormatsByArgumentIndex方法,而不是使用setFormats
MessageFormat pattform = newMessageFormat("There {0} on {1}");
pattform.setFormats(testFormats);
//進行fomat
Object[] testArgs = {null, "ADisk",null};
for (int i = 0; i < 4; ++i) {
testArgs[0] = new Integer(i);
testArgs[2] = testArgs[0];
//此時的testArgs值爲{0, "ADisk",0}
//根據MessageFormat的定義,對testArgr元素進行處理
System.out.println(pattform.format(testArgs));
}
1.5.5. ChoiceFormat的pattern構造方法
ChoiceFormat還有另外一個構造方法,傳入pattern。
爲ChoiceFormat 對象指定一個模式是相當直接的。例如:
ChoiceFormat fmt= new ChoiceFormat(
"-1#is negative| 0#is zero orfraction | 1#is one |1.0<is 1+ |2#is two |2<is more than 2.");
其中數字#是按照大小順序排列的, formate方法中傳入參數x,如果x在0,1之間,則按照0處理。
另外在對數字進行格式化時,也可以考慮使用java.math.BigDecimal。
如setScale(int newScale,int roundingMode):newScale指精確度,即保留幾位小數。roundingMode指舍入模式,常用的是四捨五入。DecimalFormat貌似只能使用四捨五入,如果使用別的舍入方式,就要使用BigDecimal了。
java.lang.Integer中的幾個轉換進制的方法也比較實用
toBinaryString(int i): 以二進制(基數 2)無符號整數形式返回一個整數參數的字符串表示形式。
toHexString(int i): 以十六進制的無符號整數形式返回一個整數參數的字符串表示形式
toOctalString(int i) :以八進制(基數 8)無符號整數形式返回一個整數參數的字符串表示形式。
Formatter類是個final的class,printf 風格的格式字符串的解釋程序,和java.text.Format中的功能有很多重複的地方。
Formatter比較常見的使用方法是String.format(format,args),System.out.printf(format,args)等。這裏只是簡單總結一下,詳細的參照api。下面的每節是對格式說明符中的元素的說明。
常規類型、字符類型和數值類型的格式說明符的語法如下:
%[argument_index$][flags][width][.precision]conversion
其中%和conversion(轉換類型)是必須的,
%表示正則表達式的開始。
可選的argument_index$,指的是參數在參數列表中的位置。如果設定argument_index$,則按照args的順序依次處理。
可選的 flags(標誌) 是修改輸出格式的字符集。有效標誌的集合取決於轉換類型。
可選 width(寬度) 是一個非負十進制整數,表明要向輸出中寫入的最少字符數。
可選 precision(精度) 是一個非負十進制整數,通常用來限制字符數。特定行爲取決於轉換類型。
2.2. 轉換(conversion)
轉換是核心,按參數類別可以分爲常規,字符,整數,浮點,日期/時間,百分比,行分隔符。不區分大小寫。
常規的返回值爲字符串,有:
b:結果爲“true/false”。參數 arg 爲 null或boolean/Boolean型的false時,返回字符串的“false”。否則返回字符串的“true”。
h:結果爲十六進制的字符串。如果參數 arg 爲 null,則結果爲 "null"。否則,結果爲調用Integer.toHexString(arg.hashCode()) 得到的結果。
s:比較常用的轉換,取得字符串。如果參數 arg 爲 null,則結果爲 "null"。如果 arg 實現 Formattable,則調用 arg.formatTo。否則,結果爲調用 arg.toString() 得到的結果。
c: 結果是一個 Unicode 字符
是對進制的操作,有:
d:結果被格式化爲十進制整數
o:結果被格式化爲八進制整數
x:結果被格式化爲十六進制整數
e:結果被格式化爲用計算機科學記數法表示的十進制數
f :結果被格式化爲十進制數
g:根據精度和舍入運算後的值,使用計算機科學記數形式或十進制格式對結果進行格式化
a:浮點 結果被格式化爲帶有效位數和指數的十六進制浮點數
t:日期和時間轉換字符的前綴。對於日期/時間的轉換,以t開頭再指定轉換內容。
如Calendar c = newGregorianCalendar(1995, MAY, 23);
String s =String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
具體參數的意義參照api。
%:結果爲字面值 '%'。
n:生成一個換行符。爲平臺相關。
2.3. 標誌(flags)
標誌有'-','#','+',' ','0',',','('。常用的是'-':將結果設爲左對齊。同時flag的使用依賴於conversion。
寬度是將向輸出中寫入的最少字符數。對於行分隔符轉換,不適用寬度,如果提供寬度,則會拋出異常。
2.5. 精度(.precision)
對於常規參數類型,精度是將向輸出中寫入的最多字符數。
對於浮點轉換 'e'、'E' 和 'f',精度是小數點分隔符後的位數。
如果轉換是 'g' 或 'G',那麼精度是舍入計算後所得數值的所有位數。如果轉換是 'a' 或 'A',則不必指定精度。
精度的優先級大於寬度。
Pattern(模式)是正則表達式的編譯表示形式,經常和java.util.regex.Matcher。Pattern沒有提供構造函數。通過調用Pattern. compile (String regex)方法來獲得實例。pattern.matcher (CharSequence input);來判斷是否input是否可以與regex匹配。compile
通過Matcher m = p.matcher("aaaaab");方法來獲得Matcher。
pattern.split(CharSequence input);可以將input分隔成一個String數組。
3.2. 關於regex
字符類比較常用, []是對字符的羅列。如[abc]。[a-z&&[^bc]] 的解釋爲a 到 z,除了 b 和 c:[ad-z](減去)。
還有字符,預定義字符類,邊界匹配器也比較常用。具體參照api。
Greedy 數量詞也需要了解。
X? 表示X,一次或一次也沒有
X* 表示X,零次或多次
X+ 表示X,一次或多次
X{n} 表示X,恰好 n 次
X{n,} 表示 X,至少 n 次
X{n,m} 表示X,至少 n 次,但是不超過 m 次。
Greedy 數量詞,這種匹配原則就叫作"貪婪" 模式。總是儘可能多的匹配符合它規則的字符。
Reluctant 數量詞,Possessive 數量詞不曉得有啥區別。
組和捕獲:捕獲組可以通過從左到右計算其開括號來編號。如(ca)(t)。
3.3. Matcher(匹配器)
通過調用模式的 matcher 方法從模式創建匹配器。創建匹配器後,可以使用它執行三種不同的匹配操作:
matches 方法嘗試將整個輸入序列與該模式匹配。 注意是整個輸入字符串。
lookingAt 嘗試將輸入序列從頭開始與該模式匹配。
find 方法掃描輸入序列以查找與該模式匹配的下一個子序列。
方法:
matcher.appendReplacement(StringBuffersb, String replacement):實現非終端追加和替換步驟。就是將模式匹配到的字符串,替換爲replacement,並將區域加入到sb中。區域的操作,參看match.region,match. regionStart, match.regionEnd。
matcher.appendTail(StringBuffersb) 實現終端追加和替換步驟。可以在一次或多次調用appendReplacement 方法後調用它來複制剩餘的輸入序列。Tail的意思尾部,也就是剩餘的意思。這裏的終端應該就是指尾部。
matcher.replaceAll(Stringreplacement):替換模式與給定替換字符串相匹配的輸入序列的每個子序列。比較方便的方法,用replacement直接替換掉與模式匹配的字符串。
與模式中的組和捕獲相關的方法,有match.group,match.groupCount。如模式(ca)(t)的groupCount就是2。