android Formatter 的使用
這幾天換租房的位置,好累啊。弄得我寫博客的習慣都沒有按時完成。之前,我在看String.format的源碼時,發現了String.format其實內服是使用了Formatter 類,但是自己對這個類不很了解,于是在網上查找資料,最終解決了問題。這里記錄一下。
先看看String.format的源碼:
public static String format(String format, Object... args) {return new Formatter().format(format, args).toString(); }整理一下關于 Formatter 的用法
實例化一個Formatter
StringBuilder builder = new StringBuilder(); //builder 用來存儲格式化后的字符串 Formatter formatter = new Formatter(builder, Locale.CHINA);format 方法,第一個參數是格式字符串,用來格式化后面的一個或多個參數。后面是一個可變參數列表。
public Formatter format(String format, Object ... args) {return format(l, format, args);}格式字符串包含固定文本能夠嵌入一個或多個格式說明符。例如:
Calendar calendar = Calendar.getInstance();String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", calendar);第一個參數是格式字符串,包含三個格式說明符,%1$tm %1$te,%1$tY,用來表明后
面的參數 calendar 改怎樣被處理以及該插入到輸出文本的什么位置。格式化字符串剩余
的部分是固定的文本包括Duke's Birthday: 和其他的空格以及標點符號。
通用類型,字符類型和數字類型的格式說明符語法如下:
argument_index 選項是一個十進制整數,用來只是要被格式化的參數在參數列表中
的位置。第一個參數用“1$”表示,第二個參數用“2$”表示,以此類推。
也可以使用另外一種方式表示參數位置,就是使用‘<’,表示使用前一個格式化說明符指向的參數。
必選項conversion 是一個字符指示參數應該怎樣被格式化。合法的conversion字符取值依賴于要被格式化的參數的數據類型。
用來格式化日期和時間類型的格式說明符語法如下,和上面的語法相比少了精度選項。
%[argument_index$][flags][width]conversionargument_index ,flags,width 選項和上面的定義一樣。必選項conversion 是一個兩個字符的序列,第一個字符必須是’t’ or ‘T’,第二個字符用來格式化參數。沒有參數對應的格式說明符具有以下語法:
Conversions 的分類
下表總結了一些轉換字符集的用法
| ‘b’,’B’ | general | 如果要被各式話的參數是null,輸出結果是false,如果參數是一個boolean或者Boolean類型的數據,輸出true或者false,其他情況返回true |
| ‘h’,’H’ | general | 如果要被各式話的參數是null,輸出結果是null,其他情況輸出Integer.toHexString(arg.hashCode()) |
| ’s’,’S’ | general | 如果要被各式話的參數是null,輸出null,如果參數實現了Formattable接口(如果要自定義Formatter的‘s’轉換說明符的功能,需要實現Formattable接口),那么會調用arg.formatTo方法,除此之外,返回結果是arg.toString() |
| ‘c’,’C’ | character | 結果是一個Unicode字符 |
| ‘d’ | integral | 結果是一個十進制整數 |
| ‘o’ | integral | 結果是一個8進制整數 |
| ‘x’,’X’ | integral | 結果是一個16進制整數 |
| ‘e’,’E’ | floating point | 結果是一個用科學計數法表示的十進制數字 |
| ‘f’ | floating point | 結果是一個十進制數字 |
| ‘g’,’G’ | floating point | 根據參數的精度和四舍五入后的值來選擇使用科學計數法或者十進制格式化 |
| ‘a’,’A’ | floating point | 結果是一個十進制數字 |
| ‘f’ | floating point | 結果是一個用基數和指數表示的十六進制浮點數 |
| ‘t’,’T’ | date/time | 日期和時間轉換字符集的第一個字符,下面細說 |
| ‘%’ | percent | 結果是一個% |
| ‘n’ | line separator | 結果是一個換行符 |
Date/Time 類型的Conversions,開始第一個字符是’t’或者 ‘T’,然后才能選擇下表中的一個。
| ‘H’ | 24小時制,結果被格式化成兩位數,如果必要以0開頭,比如07,(范圍00-23) |
| ‘I’ | 12小時制,結果被格式化成兩位數,如果必要以0開頭,比如07,(范圍01-12) |
| ‘k’ | 24小時制,范圍(0-23) |
| ‘l’ | 12小時制,范圍(1-12) |
| ‘M’ | 一小時內的分鐘數,會被格式化為兩位數,必要的話以0開頭,范圍(00-59) |
| ‘S’ | 一分鐘內的秒數,會被格式化為兩位數,必要的話以0開頭,(范圍00-60,60是一個特殊的值,要求支持描述跳變) |
| ‘L’ | 一秒內的毫秒數,結果被格式化成3位數字,必要的話以0開頭范圍(000-999) |
| ‘N’ | 一秒內的納秒數,會被格式化成9位數字,必要的話以0開頭,范圍(000000000-999999999) |
| ‘p’ | 特定語言環境下,早上或者下午的小寫標記,‘am’或者‘pm’,可以使用轉化前綴‘T’,輸出大寫的‘AM’,或者‘PM’ |
| ‘z’ | RFC 822樣式的數字時區不同于GMT,例如 -0800。 該值將根據夏令時進行調整。因為對于long, Long, and Date,java虛擬機實例使用默認的時區。 |
| ‘Z’ | 表示時區縮寫的字符串。該值將根據夏令時進行調整。因為對于long, Long, and Date,java虛擬機實例使用默認的時區。Formatter的語言環境會替代要被各式化的參數的語言環境。 |
| ’s’ | 從UTC(協調世界時)1970年1月1日00:00:00開始的開始的秒數,范圍Long.MIN_VALUE/1000到Long.MAX_VALUE/1000. |
| ‘Q’ | 從UTC(協調世界時)1970年1月1日00:00:00開始的開始的毫秒數,范圍從 Long.MIN_VALUE/1000到Long.MAX_VALUE/1000.精度受操作系統或者硬件影響。 |
下列的conversion 字符用來格式化日期
| ‘B’ | 特定語言環境下的月份的全名,例如”January”, “February” |
| ‘b’ | 特定語言環境下的月份的簡稱,例如”Jan”, “Feb”. |
| ‘h’ | 特定語言環境下的月份的簡稱,例如”Jan”, “Feb”. |
| ‘A’ | 特定語言環境下的一周的某一天的全名,例如”Sunday”, “Monday” |
| ‘a’ | 特定語言環境下的一周的某一天的簡稱,例如”Sun”, “Mon” |
| ‘C’ | 四位的年數除以100,格式化成兩位數,如果有必要的話,以0開頭。范圍(00 - 99) |
| ‘Y’ | 年,被格式化成至少4位整數,必要的話,以0開頭。例如0092就是格林尼治時間的公元92年。 |
| ‘y’ | 年的最后兩位,如果必要,以0開頭(范圍00-99) |
| ‘j’ | 一年的某一天,被格式化成3位數,范圍(0-366) |
| ‘m’ | 月,被格式化成兩位數,必要的話以0開頭,范圍(01,13) |
| ‘d’ | 一個月中的某一天,被格式化成兩位,如果必要的話,以0開頭,范圍(01,31) |
| ‘e’ | 一個月中的某一天,被格式化成兩位 范圍(1 - 31) |
下面的conversion 字符串是格式化date/time的組合。
| ‘R’ | 把時間格式化成24小時的格式,和”%tH:%tM” 效果一樣 |
| ‘T’ | 把時間格式化成24小時的格式,和 “%tH:%tM:%tS” 效果一樣 |
| ‘r’ | 把時間格式化成24小時的格式, 和”%tI:%tM:%tS %Tp”效果一樣早晨或下午標記(’%Tp’)是依賴于區域設置的。 |
| ‘F’ | 被格式化成 ISO 8601完整格式的日期 等價于 “%tY-%tm-%td”. |
| ‘D’ | 日期格式化,和 “%tY-%tm-%td”效果一樣 |
| ‘c’ | 日期格式化,和 “%ta %tb %td %tT %tZ %tY”效果一樣,例如 “Sun Jul 20 16:17:00 EDT 1969” |
注意
'B', 'H', 'S', 'C', 'X', 'E', 'G', 'A', and 'T'這幾個converion 大寫小寫都可以,輸出結果也會對應輸出大小寫。
下表是可用的flags。y 表示對應的參數類型可用,no 表示對應的參數類型不可用。
| ‘-‘ | y | y | y | y | y | 輸出結果左對齊 |
| ‘#’ | y1 | no | y3 | y | no | 輸出結果和conversion相關的變換格式 |
| ‘+’ | no | no | y4 | y | no | 輸出結果包括一個符號 |
| ’ ‘(空格) | no | no | y4 | y | no | 如果輸出結果是一個正數,結果前面會有一個空格 |
| ‘0’ | no | no | y | y | no | 如果輸出結果的寬度小于指定的寬度,用0來補齊 |
| ‘,’(逗號) | no | no | y2 | y5 | no | 輸出結果包括特定語言環境下的組分隔符,類似這樣,格式化100000,輸出100,000 |
| ‘(‘ | no | no | y4 | y5 | no | 輸出結果會把負值用括號包起來,類似這樣,格式化-100,輸出(100) |
注意
y5后面的conversion 只能是 ‘e’, ‘E’, ‘f’, ‘g’。
Width
width 是輸出結果最少的字符數。不能用于換行符。
Precision(精度)
對于通用類型Conversions ,精度是輸出結果最少的字符數。
對于浮點型Conversions :’e’, ‘E’, and ‘f’,精度表示小數點后保留幾位小數;如果conversion是 ‘g’ or ‘G’,精度表示四舍五入以后,結果的總位數;如果conversion是“a”或“A”,則不能指定精度。
光說不練假把式一個個試試看結果。
Date/Time
conversion 第一個字符必須是 ‘t’or ‘T’
Date date = new Date();long time = date.getTime();builder.delete(0, builder.length());formatter.format("%1$tH:%1$tM:%1$tS %1$tp", time);Log.e(tag, builder.toString());//MainActivity: 13:37:37 下午builder.delete(0, builder.length());formatter.format("%1$tR", time);Log.e(tag, builder.toString());//13:37builder.delete(0, builder.length());formatter.format("%1$tT", time);Log.e(tag, builder.toString());//13:37:37builder.delete(0, builder.length());formatter.format("%1$tr", time);Log.e(tag, builder.toString());//01:37:37 下午builder.delete(0, builder.length());formatter.format("%1$tY-%1$tm-%1$td %1$tB %1$ta", date);Log.e(tag, builder.toString());//2017-01-14 一月 周六builder.delete(0, builder.length());formatter.format("%1$tD", date);Log.e(tag, builder.toString());//01/14/17builder.delete(0, builder.length());formatter.format("%1$tF", date);Log.e(tag, builder.toString());//2017-01-14builder.delete(0, builder.length());formatter.format("%1$tc", date);Log.e(tag, builder.toString());//周六 1月 14 13:37:37 GMT+08:00 2017Percent and Line Separator
builder.delete(0, builder.length());formatter.format("%1$d%%100%n good afternoon", 100);Log.e(tag, builder.toString());//輸出結果MainActivity: 100%100good afternoon有一個換行。
簡單講講,其實Formatter格式化字符和之前的String.format基本一致,因為String.format內部就是調用的formatter.format。formatter.format的第一個參數傳格式化的字符串,需要符合一些要求。下面在具體的講講。
1.對整數進行格式化:%[index$][標識][最小寬度]轉換方式
我們可以看到,格式化字符串由4部分組成,其中%[index$]的含義我們上面已經講過,[最小寬度]的含義也很好理解,就是最終該整數轉化的字符串最少包含多少位數字。我們來看看剩下2個部分的含義吧:
?
標識:?'-'????在最小寬度內左對齊,不可以與“用0填充”同時使用
'#'????只適用于8進制和16進制,8進制時在結果前面增加一個0,16進制時在結果前面增加0x
'+'????結果總是包括一個符號(一般情況下只適用于10進制,若對象為BigInteger才可以用于8進制和16進制)
'??'????正值前加空格,負值前加負號(一般情況下只適用于10進制,若對象為BigInteger才可以用于8進制和16進制)
'0'????結果將用零來填充
','????只適用于10進制,每3位數字之間用“,”分隔
'('????若參數是負數,則結果中不添加負號而是用圓括號把數字括起來(同‘+’具有同樣的限制)
轉換方式:
d-十進制???o-八進制???x或X-十六進制
?
??????? 上面的說明過于枯燥,我們來看幾個具體的例子。需要特別注意的一點是:大部分標識字符可以同時使用。
?
????????System.out.println(String.format("%1$,09d",?-3123));????????System.out.println(String.format("%1$9d",?-31));
????????System.out.println(String.format("%1$-9d",?-31));
????????System.out.println(String.format("%1$(9d",?-31));
????????System.out.println(String.format("%1$#9x",?5689));
//結果為:
//-0003,123
//??????-31
//-31??????
//?????(31)
//???0x1639
?
2.對浮點數進行格式化:%[index$][標識][最少寬度][.精度]轉換方式
??????? 我們可以看到,浮點數的轉換多了一個“精度”選項,可以控制小數點后面的位數。
?
標識:?'-'????在最小寬度內左對齊,不可以與“用0填充”同時使用
'+'????結果總是包括一個符號
'??'????正值前加空格,負值前加負號
'0'????結果將用零來填充
','????每3位數字之間用“,”分隔(只適用于fgG的轉換)
'('????若參數是負數,則結果中不添加負號而是用圓括號把數字括起來(只適用于eEfgG的轉換)
轉換方式:
'e',?'E'??--??結果被格式化為用計算機科學記數法表示的十進制數
'f'??????????--??結果被格式化為十進制普通表示方式
'g',?'G'????--??根據具體情況,自動選擇用普通表示方式還是科學計數法方式
'a',?'A'????--???結果被格式化為帶有效位數和指數的十六進制浮點數
3.對字符進行格式化:
??????? 對字符進行格式化是非常簡單的,c表示字符,標識中'-'表示左對齊,其他就沒什么了。
4.對百分比符號進行格式化:
??????? 看了上面的說明,大家會發現百分比符號“%”是特殊格式的一個前綴。那么我們要輸入一個百分比符號該怎么辦呢?肯定是需要轉義字符的,但是要注意的是,在這里轉義字符不是“\”,而是“%”。換句話說,下面這條語句可以輸出一個“12%”:
System.out.println(String.format("%1$d%%", 12));
5.取得平臺獨立的行分隔符:
??????? System.getProperty("line.separator")可以取得平臺獨立的行分隔符,但是用在format中間未免顯得過于煩瑣了。于是format函數自帶了一個平臺獨立的行分隔符那就是String.format("%n")。
6.對日期類型進行格式化:
???????? 以下日期和時間轉換的后綴字符是為 't' 和 'T' 轉換定義的。這些類型相似于但不完全等同于那些由 GNU date 和 POSIX strftime(3c) 定義的類型。提供其他轉換類型是為了訪問特定于 Java 的功能(如將 'L' 用作秒中的毫秒)。
以下轉換字符用來格式化時間:
'H' ??? 24 小時制的小時,被格式化為必要時帶前導零的兩位數,即 00 - 23。
'I' ??? 12 小時制的小時,被格式化為必要時帶前導零的兩位數,即 01 - 12。
'k' ??? 24 小時制的小時,即 0 - 23。
'l' ??? 12 小時制的小時,即 1 - 12。
'M' ??? 小時中的分鐘,被格式化為必要時帶前導零的兩位數,即 00 - 59。
'S' ??? 分鐘中的秒,被格式化為必要時帶前導零的兩位數,即 00 - 60 ("60" 是支持閏秒所需的一個特殊值)。
'L' ??? 秒中的毫秒,被格式化為必要時帶前導零的三位數,即 000 - 999。
'N' ??? 秒中的毫微秒,被格式化為必要時帶前導零的九位數,即 000000000 - 999999999。
'p' ??? 特定于語言環境的 上午或下午 標記以小寫形式表示,例如 "am" 或 "pm"。使用轉換前綴 'T' 可以強行將此輸出轉換為大寫形式。
'z' ??? 相對于 GMT 的 RFC 822 格式的數字時區偏移量,例如 -0800。
'Z' ??? 表示時區縮寫形式的字符串。Formatter 的語言環境將取代參數的語言環境(如果有)。
's' ??? 自協調世界時 (UTC) 1970 年 1 月 1 日 00:00:00 至現在所經過的秒數,即 Long.MIN_VALUE/1000 與 Long.MAX_VALUE/1000 之間的差值。
'Q' ??? 自協調世界時 (UTC) 1970 年 1 月 1 日 00:00:00 至現在所經過的毫秒數,即 Long.MIN_VALUE 與 Long.MAX_VALUE 之間的差值。
以下轉換字符用來格式化日期:
'B' ??? 特定于語言環境的月份全稱,例如 "January" 和 "February"。
'b' ??? 特定于語言環境的月份簡稱,例如 "Jan" 和 "Feb"。
'h' ??? 與 'b' 相同。
'A' ??? 特定于語言環境的星期幾全稱,例如 "Sunday" 和 "Monday"
'a' ??? 特定于語言環境的星期幾簡稱,例如 "Sun" 和 "Mon"
'C' ??? 除以 100 的四位數表示的年份,被格式化為必要時帶前導零的兩位數,即 00 - 99
'Y' ??? 年份,被格式化為必要時帶前導零的四位數(至少),例如,0092 等于格里高利歷的 92 CE。
'y' ??? 年份的最后兩位數,被格式化為必要時帶前導零的兩位數,即 00 - 99。
'j' ??? 一年中的天數,被格式化為必要時帶前導零的三位數,例如,對于格里高利歷是 001 - 366。
'm' ??? 月份,被格式化為必要時帶前導零的兩位數,即 01 - 13。
'd' ??? 一個月中的天數,被格式化為必要時帶前導零兩位數,即 01 - 31
'e' ??? 一個月中的天數,被格式化為兩位數,即 1 - 31。
以下轉換字符用于格式化常見的日期/時間組合。
'R' ??? 24 小時制的時間,被格式化為 "%tH:%tM"
'T' ??? 24 小時制的時間,被格式化為 "%tH:%tM:%tS"。
'r' ??? 12 小時制的時間,被格式化為 "%tI:%tM:%tS %Tp"。上午或下午標記 ('%Tp') 的位置可能與語言環境有關。
'D' ??? 日期,被格式化為 "%tm/%td/%ty"。
'F' ??? ISO 8601 格式的完整日期,被格式化為 "%tY-%tm-%td"。
'c' ??? 日期和時間,被格式化為 "%ta %tb %td %tT %tZ %tY",例如 "Sun Jul 20 16:17:00 EDT 1969"。
簡單講講,其實格式化不同的內容,format參數的要求是不一樣的。最常用的形式是%[index$][標識][最少寬度][.精度]轉換方式來格式化整數或浮點數,其他的大家可以看看,上面講的很詳細,這里總結的話好難。
還有需要注意一點,Formatter formatter = new Formatter(builder, Locale.CHINA);每次格式化后需要報builder的內容清空,不然每次的結果會拼接起來,導致輸出結果不正確。每次調用formatter.format();后調用builder.delete(0, builder.length())清空就可以了。
android Formatter 的使用就講完了。
就這么簡單。
總結
以上是生活随笔為你收集整理的android Formatter 的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android SQLite数据库的使用
- 下一篇: android 将IE设为默认打开的浏览