Java格式转换之(FieldPosition(跟踪索引)标识要格式化的类型为)

Java格式转换


java.text.Format

Format是一个用于格式化语言环境敏感的信息(如日期、消息和数字)的抽象基类,直接已知子类有DateFormat, MessageFormat, NumberFormat。

Format定义了编程接口,用于将语言环境敏感的对象格式化为String(使用format方法)和将String重新解析为对象(使用 parseObject方法)。 

通常,一个Format的parseObject方法必须能解析任何由其Format方法格式化的字符串。不过,也可能存在不能解析的异常情况。例如,Format方法可能创建中间无分隔符的两个相邻整数,在这种情况下,parseObject无法判断哪个数字属于哪个数。

Java平台为格式化日期、消息和数字分别提供了三个特殊的Format的子类:DateFormat、MessageFormat和NumberFormat。具体的子类必须实现三个方法: 

format(Object obj, StringBuffer toAppendTo, FieldPosition pos) 

formatToCharacterIterator(Object obj) 

parseObject(String source, ParsePosition pos) 

这些常规方法允许对对象进行多态解析和格式化,还可以被使用(如被 MessageFormat 使用)。子类通常也为特定的输入类型提供了另外的format方法,也为特定的结果类型提供了parse方法。当在输入文本的开始没有任何所需格式的文本时,则任何不带 ParsePosition参数的parse方法都应该抛出ParseException。 

大多数子类还将实现以下工厂方法: 

getInstance 获取一个适合于当前语言环境的有用的格式对象 

getInstance(Locale) 获取一个适合于指定语言环境的有用的格式对象。 

此外,某些子类还可能为了更特殊的控制实现其它getXxxxInstance方法。例如,NumberFormat类提供了getPercentInstance和 getCurrencyInstance方法来获取特殊的数字格式器。

Format的子类如果允许程序员能为不同语言环境(比如用getInstance(Locale) )创建对象,必须实现以下类方法: 

public static Locale[] getAvailableLocales()

最后子类定义一个常量集合来标识格式输出中的不同字段。这些常量用于创建一个FieldPosition对象该对象标识字段中所包含的信息及其在格式化结果中的位置。这些常量应当命名为item_FIELD,其中item标识了该字段。有关这些常量的例子,请参阅 ERA_FIELD及其在DateFormat中的同类。

格式通常不是同步的。建议为每个线程创建独立的格式实例。如果多个线程同时访问一个格式,其它必须保持外部同步。


java.text.FieldPosition

构造方法

public FieldPosition(int field)

为给定字段创建一个FieldPosition对象。字段由常量标识,在不同的Format子类中,常量名称一般以_FIELD结尾。

public FieldPosition(Format.Field attribute)

为给定的字段常量创建一个FieldPosition对象。字段由不同Format子类中定义的常量来标识。这等效于调用new FieldPosition(attribute, -1)。


public FieldPosition(Format.Field attribute,int fieldID)

为给定的字段创建一个FieldPosition对象。字段由来自Field的子类之一的属性常量以及一个由Format的子类定义的整型字段ID标识。

当attribute不为null时,需要使用Field的Format子类应当优先考虑attribute而忽略fieldID。

不过,旧的Format子类可能不知道Field而依靠fieldID。如果该字段没有相应的整型常量,则fieldID应为-1。


FieldPosition是Format及其子类用于在格式输出中(format(Object obj, StringBuffer toAppendTo, FieldPosition pos))标识字段的简单类。

FieldPosition保持对格式输出中字段位置的两个索引进行跟踪:字段的第一个字符的索引和紧跟字段的最后一个字符的索引。 

new FieldPosition(NumberFormat.INTEGER_FIELD);

stringBuffer1 = 1.235

 INTEGER:beginIndex=0,endIndex=1     //索引位0-1(跟踪索引位)

new FieldPosition(NumberFormat.FRACTION_FIELD);

stringBuffer2 = 1.235

FRACTION:beginIndex=2,endIndex=5   //索引位2-5(跟踪索引位)

不同的Format类中的format方法需要一个FieldPosition对象作为参数。使用此format方法执行部分格式化或者以获取格式化输出的信息(比如字段位置)。字段可以通过两种方式标识,两者的作用是一致的,只是Format.Field常量更详细,建议使用这种方式: 

1、通过一个其名称通常以_FIELD结尾的整型常量。这些常量在Format的不同子类中定义: 

NumberFormat

static int FRACTION_FIELD

          用于构造FieldPosition对象的字段常量。

static int INTEGER_FIELD

          用于构造FieldPosition对象的字段常量。

总结:二者的跟踪的索引位不同




例子:

public static void main(String[] args) {

        //建立一个数字格式化对象

        NumberFormat numberFormat = NumberFormat.getInstance();

        //建立字符数组缓冲器)—— 线程安全

        StringBuffer stringBuffer1 = new StringBuffer();

        //数字格式化,用于格式化时对索引跟踪(第一个字符的索引,紧跟字段最后一个字符的索引)

        FieldPosition fieldPosition = new FieldPosition(NumberFormat.INTEGER_FIELD);

        //十进位小数对象

        BigDecimal bigDecimal = new BigDecimal("1.23456789");

        //执行格式化

        stringBuffer1 = numberFormat.format(bigDecimal, stringBuffer1, fieldPosition);

        System.out.println("stringBuffer1 = " + stringBuffer1);  //结果为1.235

        //获取索引

        System.out.println("INTEGER:beginIndex=" + fieldPosition.getBeginIndex() + ",endIndex=" + fieldPosition.getEndIndex());

        fieldPosition = new FieldPosition(NumberFormat.FRACTION_FIELD);

        StringBuffer stringBuffer2 = new StringBuffer();

        stringBuffer2 = numberFormat.format(bigDecimal, stringBuffer2, fieldPosition);

        System.out.println("stringBuffer2 = " + stringBuffer2);

        System.out.println("FRACTION:beginIndex=" + fieldPosition.getBeginIndex() + ",endIndex=" + fieldPosition.getEndIndex());

    }

结果为:

stringBuffer1 = 1.235

  INTEGER:beginIndex=0,endIndex=1     //索引位0-1

stringBuffer2 = 1.235

FRACTION:beginIndex=2,endIndex=5   //索引位2-5


2、通过一个Format.Field常量:标识要格式化的类型是什么?

NumberFormat.Field

static NumberFormat.Field CURRENCY

          标识货币字段的常量。

static NumberFormat.Field DECIMAL_SEPARATOR

          标识小数点字段的常量。

static NumberFormat.Field EXPONENT

          标识指数字段的常量。

static NumberFormat.Field EXPONENT_SIGN

          标识指数符号 (exponent sign) 字段的常量。

static NumberFormat.Field EXPONENT_SYMBOL

          标识指数符号 (exponent symbol) 字段的常量。

static NumberFormat.Field FRACTION

          标识小数字段的常量。

static NumberFormat.Field GROUPING_SEPARATOR

          标识组分隔符字段的常量。

static NumberFormat.Field INTEGER

          标识整数字段的常量。

static NumberFormat.Field PERCENT

          标识百分数字段的常量。

static NumberFormat.Field PERMILLE

          标识千分数字段的常量。

static NumberFormat.Field SIGN

          标识符号字段的常量。

  FieldPosition pos = new FieldPosition(DateFormat.Field.DAY_OF_MONTH);

          标识日期字段的常量


public static void main(String[] args) {

        NumberFormat numberFormat = NumberFormat.getInstance();

        StringBuffer stringBuffer1 = new StringBuffer();

        FieldPosition fieldPosition = new FieldPosition(NumberFormat.Field.INTEGER);

        BigDecimal bigDecimal = new BigDecimal("1.23456789");

        stringBuffer1 = numberFormat.format(bigDecimal, stringBuffer1, fieldPosition);

        System.out.println("stringBuffer1 = " + stringBuffer1);

        System.out.println("INTEGER:beginIndex=" + fieldPosition.getBeginIndex() + ",endIndex=" + fieldPosition.getEndIndex());

        fieldPosition = new FieldPosition(NumberFormat.Field.FRACTION);

        StringBuffer stringBuffer2 = new StringBuffer();

        stringBuffer2 = numberFormat.format(bigDecimal, stringBuffer2, fieldPosition);

        System.out.println("stringBuffer2 = " + stringBuffer2);

        System.out.println("FRACTION:beginIndex=" + fieldPosition.getBeginIndex() + ",endIndex=" + fieldPosition.getEndIndex());

    }

输出结果:

stringBuffer1 = 1.235

INTEGER:beginIndex=0,endIndex=1

stringBuffer2 = 1.235

FRACTION:beginIndex=2,endIndex=5


public static void main(String[] args) {

        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);

        StringBuffer stringBuffer = new StringBuffer();

        FieldPosition pos = new FieldPosition(DateFormat.Field.DAY_OF_MONTH);

        stringBuffer = dateFormat.format(new Date(), stringBuffer, pos);

        System.out.println("stringBuffer = " + stringBuffer);

        System.out.println("DATE_FIELD:beginIndex= " + pos.getBeginIndex() + ",endIndex=" + pos.getEndIndex());

    }

输出结果:

stringBuffer = 2016年6月28日 上午11时07分18秒

DATE_FIELD:beginIndex= 7,endIndex=9


java.text.ParsePosition

ParsePosition是Format及其子类所使用的简单类,用来在解析过程中跟踪当前位置。各种Format类中的parseObject方法要求将 ParsePosition对象作为一个变量。解析具有不同格式的字符串时,可以使用同一个ParsePosition,因为索引参数记录的是当前位置。ParsePosition也会记录解析错误的位置。


构造方法

public ParsePosition(int index)

创建一个具有给定初始索引的新 ParsePosition。


例子:

public static void main(String[] args) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        String strings[] = {"xxx 2016-06-28 xxx1", "20160628 xxx2"};

        for (int i = 0; i < strings.length; i++) {

            ParsePosition parsePosition = new ParsePosition(4);//从第四位开始处理

            Date date = simpleDateFormat.parse(strings[i], parsePosition);

            //解析错误,返回null

            if (date == null) {

                System.out.println("无效日期:" + strings[i]);

                System.out.println("解析出错的索引=" + parsePosition.getErrorIndex());

                System.out.println("当前索引=" + parsePosition.getIndex());

                continue;

            }

            String substring = strings[i].substring(parsePosition.getIndex());

            System.out.println("日期=" + date + ",剩余部分:" + substring);

        }

    }

日期=Tue Jun 28 00:00:00 CST 2016,剩余部分: xxx1

无效日期:20160628 xxx2

解析出错的索引=8

当前索引=4

java.text.NumberFormat

NumberFormat 是所有数值格式的抽象基类。此类提供格式化和解析数值的接口。NumberFormat 还提供了一些方法来确定哪些语言环境具有数值格式,以及它们的名称是什么。 

NumberFormat 可用于格式化和解析任何语言环境的数值。使代码能够完全独立于小数点、千位分隔符甚至所用特定小数位数的语言环境约定,并与数值格式是否为偶小数无关。


如何获得一个实例?

NumberFormat总共有三种实例,常规数值、货币数值,百分比数值,每种都可以用默认语言环境和指定语言环境。

常规数值:getInstance()(同getNumberInstance())、getInstance(Locale inLocale)(同getNumberInstance(Locale inLocale))

货币数值:getCurrencyInstance()、getCurrencyInstance(Locale inLocale)

百分比数值:getPercentInstance()、getPercentInstance(Locale inLocale)


public static Locale[] getAvailableLocales()

返回一个当前所支持的语言环境数组


void setCurrency(Currency currency) 

设置格式化货币值时此数值格式使用的货币。

void setGroupingUsed(boolean newValue) 

设置此格式中是否使用分组,即是否有千位分隔符(逗号)。


void setMaximumFractionDigits(int newValue) 

设置数的小数部分所允许的最大位数。与解析无关。

void setMaximumIntegerDigits(int newValue) 

设置数的整数部分所允许的最大位数。与解析无关。

void setMinimumFractionDigits(int newValue) 

设置数的小数部分所允许的最小位数。与解析无关。

void setMinimumIntegerDigits(int newValue) 

设置数的整数部分所允许的最小位数。与解析无关。

void setParseIntegerOnly(boolean value) 

设置数是否应该仅作为整数进行解析。与格式化无关。


例子:

public static void main(String[] args) throws Exception {

        //常规数值

        NumberFormat format1 = NumberFormat.getNumberInstance();

        System.out.println(format1.getMaximumIntegerDigits());//2147483647

        System.out.println(format1.getMinimumIntegerDigits());//1

        System.out.println(format1.getMaximumFractionDigits());//3

        System.out.println(format1.getMinimumFractionDigits());//0

        System.out.println(format1.isGroupingUsed());//true

        System.out.println(format1.isParseIntegerOnly());//false

        System.out.println(format1.format(10000000));//10,000,000 默认分组

        System.out.println(format1.format(10000000.000));//10,000,000 小数点后全身0,被舍弃

        System.out.println(format1.format(10000000.001));//10,000,000.001

        System.out.println(format1.format(10000000.0001));//10,000,000 默认最大小数位数是3位

        System.out.println(format1.parse("10000000.001"));//1.0000000001E7 默认可以解析小数

        format1.setParseIntegerOnly(true);

        System.out.println(format1.parse("10000000.001"));//10000000

        //百分比数值

        NumberFormat format2 = NumberFormat.getPercentInstance();

        System.out.println(format2.getMaximumIntegerDigits());//2147483647

        System.out.println(format2.getMinimumIntegerDigits());//1

        System.out.println(format2.getMaximumFractionDigits());//0

        System.out.println(format2.getMinimumFractionDigits());//0

        System.out.println(format2.isGroupingUsed());//true

        System.out.println(format2.isParseIntegerOnly());//false

        System.out.println(format2.format(1.01));//101%

        System.out.println(format2.format(1.001));//100% 默认最大小数位数是0

        format2.setMaximumFractionDigits(1);

        System.out.println(format2.format(1.001));//100.1%

        System.out.println(format2.parse("100.1%"));// 1.001 默认可以解析小数

        //货币格式

        NumberFormat format3 = NumberFormat.getCurrencyInstance();

        System.out.println(format3.getMaximumIntegerDigits());//2147483647

        System.out.println(format3.getMinimumIntegerDigits());//1

        System.out.println(format3.getMaximumFractionDigits());//2

        System.out.println(format3.getMinimumFractionDigits());//2

        System.out.println(format3.isGroupingUsed());//true

        System.out.println(format3.isParseIntegerOnly());//false

        System.out.println(format3.format(10000));//¥10,000.00 默认语言环境是zh_CN

        System.out.println(format3.parse("¥10,000.00"));//10000

    }


java.text.DecimalFormat

DecimalFormat是NumberFormat的一个具体子类,用于格式化十进制数字。该类设计有各种功能,使其能够解析和格式化任意语言环境中的数,包括对西方语言、阿拉伯语和印度语数字的支持。通常不直接调用DecimalFormat的构造方法,要获取具体语言环境的DecimalFormat(包括默认语言环境),可调用NumberFormat的某个工厂方法,如getInstance()。如果看源码会发现getInstance()其实返回的就是DecimalFormat实例,因为以后的版本NumberFormat的工厂方法可能返回不同于DecimalFormat的子类: 

NumberFormat f = NumberFormat.getInstance(loc);

if (f instanceof DecimalFormat) {

    ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);

}

DecimalFormat包含一个模式和一组符号。可直接使用applyPattern()或间接使用API方法来设置模式。符号存储在DecimalFormatSymbols象中。如果想要改变符号,比如小数点,可以使用和DecimalFormate关联的DecimalFormatSymbols,此类表示了DecimalFormat格式化数字所需的符号集(如小数点、组分隔符等等)。DecimalFormat 根据其语言环境数据为其自身创建一个DecimalFormatSymbols实例。如果需要更改这些符号,可从DecimalFormat#getDecimalFormatSymbols()获得DecimalFormatSymbols对象并修改它。通常程序员不需要修改DecimalFormatSymbols。


特殊符号

0

数字。阿拉伯数字,如果当前位置不存在数字,则显示为0

#

数字。阿拉伯数字,在不影响数值的情况下,当前位置如果为0或者不存在,则不显示

.

数字。小数分隔符或货币小数分隔符

-

数字。减号

,

数字。分组分隔符

E

数字。分隔科学计数法中的尾数和指数。在前缀或后缀中无需加引号

;

子模式边界。分隔正数和负数子模式

%

前缀或后缀。乘以 100 并显示为百分数

\u2030

前缀或后缀。乘以 1000 并显示为千分数

¤(\u00A4)

前缀或后缀。货币记号,由货币符号替换。如果两个同时出现,则用国际货币符号替换。如果出现在某个模式中,则使用货币小数分隔符,而不使用小数分隔符

前缀或后缀。用于在前缀或或后缀中为特殊字符加引号,例如 "‘#‘#" 将 123 格式化为 "#123"。要创建单引号本身,请连续使用两个单引号:"# o‘‘clock"



语法

1、前缀和后缀:数字前后的符号,除 \uFFFE、\uFFFF 和特殊字符以外的所有 Unicode 字符。

2、小数分隔符和千位分隔符应该是不同的字符,否则将不可能进行解析。

3、如果使用具有多个分组字符的模式,则最后一个分隔符和整数结尾之间的间隔才是使用的分组大小。所以 "#,##,###,####" == "######,####" == "##,####,####"。 



构造方法

DecimalFormat() 

使用默认模式和默认语言环境的符号创建一个DecimalFormat。 

DecimalFormat(String pattern) 

使用给定的模式和默认语言环境的符号创建一个DecimalFormat。 

DecimalFormat(String pattern, DecimalFormatSymbols symbols) 

使用给定的模式和符号创建一个DecimalFormat。 


例子:

public static void main(String[] args) throws Exception {

        DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols();

        unusualSymbols.setDecimalSeparator(‘|‘);

        unusualSymbols.setGroupingSeparator(‘^‘);

        String strange = "#,##0.###";

        DecimalFormat weirdFormatter = new DecimalFormat(strange, unusualSymbols);

        weirdFormatter.setGroupingSize(4);

        String bizarre = weirdFormatter.format(12345.678);

        System.out.println(bizarre);//1^2345|678

    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,598评论 18 399
  • 一、Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计...
    子非鱼_t_阅读 4,164评论 1 44
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 母亲很久以前就说我冷血,像个没有感情的动物,脸上什么时候都是一副无所谓的表情,好像扬坤还有一首叫什么来着?哦!叫“...
    六六sy阅读 717评论 4 4
  • 寒月东风慄凛,青灯盏盏未寝,怨语夜未休,孤枕青霜白鬓。望尽、望尽,君去红颜辞镜。
    不无草堂主人阅读 282评论 0 1