numberformat_解决NumberFormat的解析问题
入門(mén)程序員很快發(fā)現(xiàn),數(shù)字的文本表示形式與程序可以在其上執(zhí)行數(shù)學(xué)運(yùn)算的數(shù)字變量明顯不同。 例如, "123"與真實(shí)數(shù)值123或十六進(jìn)制0x7B 。 程序必須使用算法或轉(zhuǎn)換例程來(lái)從文本中獲取數(shù)字-尤其是當(dāng)文本使用分組或小數(shù)點(diǎn)分隔符(例如美國(guó)數(shù)字格式的逗號(hào)和小數(shù)點(diǎn))格式化時(shí)。 文本到數(shù)字的轉(zhuǎn)換首先是交互式編程的一個(gè)問(wèn)題,但是HTML,XML以及許多其他將數(shù)據(jù)作為文本處理的文件和通信格式也經(jīng)常遇到這種情況。
在Java SE API提供了類(lèi)似的方法Integer.parseInt()和Double.parseDouble()進(jìn)行轉(zhuǎn)換,但這些方法預(yù)計(jì)在Java語(yǔ)言規(guī)范文本(見(jiàn)定義的形式他們的論據(jù)相關(guān)主題 )。 就本文而言,它主要查看整數(shù)和雙精度數(shù),該格式基本上僅由以下字符組成:
- 前導(dǎo)減號(hào)(ASCII值45或十六進(jìn)制0x2D )
- 數(shù)字0到9(ASCII值48到57或十六進(jìn)制0x30到0x39 )
- 對(duì)于浮點(diǎn)值,用點(diǎn)或句點(diǎn)表示的小數(shù)點(diǎn)(ASCII值46或十六進(jìn)制0x2E )
該要求對(duì)于程序員和代碼是合理的,但是用戶希望以其本地文化的通用格式輸入和查看數(shù)字。 Java SE API的java.text.NumberFormat類(lèi)包含一個(gè)方便的parse(String source)方法,大多數(shù)程序員都使用該方法將特定于語(yǔ)言環(huán)境的格式化文本解析為數(shù)字值。 不幸的是,該方法可能會(huì)產(chǎn)生意想不到的錯(cuò)誤結(jié)果。 本文介紹了NumberFormat的原理,回顧了其功能,公開(kāi)了類(lèi)的解析陷阱,并提供了可靠使用它的指導(dǎo)原則。
無(wú)需驗(yàn)證即可解析
本文的示例程序(請(qǐng)參閱下載 ) NumberInput (圖1所示)是一個(gè)Swing應(yīng)用程序,可讓您探索幾種將文本輸入轉(zhuǎn)換為數(shù)值的方法。 除輸入字段外,該程序還顯示默認(rèn)的語(yǔ)言環(huán)境名稱(chēng),原始鍵值,原始長(zhǎng)度和已解析的位置數(shù)(如果適用)。 在啟動(dòng)時(shí),它將分別使用雙123456.7值123456.7和整數(shù)值1234567加載輸入字段。 這兩個(gè)值均按照本機(jī)用戶期望的格式設(shè)置為默認(rèn)語(yǔ)言環(huán)境。 因?yàn)槲易≡诿绹?guó),程序會(huì)顯示"123,456.7"的雙重價(jià)值, "1,234,567"的整數(shù)值。
圖1. NumberInput初始顯示
當(dāng)您單擊NoCheck按鈕時(shí),該程序使用Double.parseDouble()和Integer.parseInt()進(jìn)行直接解析,而無(wú)需進(jìn)行驗(yàn)證。 請(qǐng)注意,在調(diào)用任何其他方法之前,會(huì)在actionPerformed()從輸入字符串中刪除前導(dǎo)和尾隨空格。 圖2顯示了結(jié)果:
圖2. Double.parseDouble()為格式化的文本拋出NumberFormatException
錯(cuò)誤的原因是逗號(hào)用作美國(guó)語(yǔ)言環(huán)境的分組分隔符。 除去逗號(hào)后,輸入為"123456.7" ,程序?qū)⒔邮躣ouble值。
負(fù)值呢? 鍵入前導(dǎo)符號(hào)(并除去逗號(hào))可使程序滿意,但后綴符號(hào)的結(jié)果為: 輸入字符串"123456.7-" NumberFormatException 。
出于相同的原因,整數(shù)分析顯示類(lèi)似的行為。 為NoCheck按鈕調(diào)用的代碼在NumberInput的noCheckInput()方法中。 它使用Double.parseDouble()從JTextField jtD輸入,并使用Integer.parseInt()從JTextField jtI輸入。 根據(jù)規(guī)則,這些結(jié)果是正常的,并且超出絕對(duì)初學(xué)者階段,對(duì)于大多數(shù)Java程序員來(lái)說(shuō),應(yīng)該是預(yù)期的行為。
搶救NumberFormat
除了錯(cuò)別字和其他用戶輸入錯(cuò)誤外,在顯示帶格式的數(shù)字文本和接收來(lái)自同一字段的數(shù)字文本輸入之間始終存在不安的關(guān)系。 我們可能已經(jīng)知道所有程序員,他們認(rèn)為解決方案僅是顯示一條消息,上面寫(xiě)著:“沒(méi)有逗號(hào)且前導(dǎo)減號(hào)的關(guān)鍵數(shù)字”。 頭腦冷靜的數(shù)據(jù)輸入人員通常對(duì)此方法沒(méi)有太大的問(wèn)題,但是用戶通常希望看到格式化的數(shù)字,然后通常直接在格式化的顯示器上鍵入內(nèi)容,從而保持分隔符和分組。 通常,經(jīng)過(guò)一番抱怨之后,美國(guó)程序員解決該問(wèn)題的第一步是編寫(xiě)一個(gè)例程,該例程去除逗號(hào)并將任何尾隨的減號(hào)移動(dòng)到輸入值的前面。 以這種方式編寫(xiě)的許多程序在生產(chǎn)中都有很長(zhǎng)的生命。 從某種意義上說(shuō),這是連程序員首次進(jìn)軍國(guó)際化(I18N)和本地化(localization)(見(jiàn)相關(guān)主題 )。 問(wèn)題在于,這種代碼只能針對(duì)一個(gè)或一組有限的語(yǔ)言環(huán)境有效地本地化程序。
Java程序被譽(yù)為能夠在任何啟用的平臺(tái)上運(yùn)行,并且許多人也以熟悉的方式將其表示為任何國(guó)家和語(yǔ)言。 Java SE SDK提供了API來(lái)使這種期望成為現(xiàn)實(shí)。 但是,像我剛才描述的第一個(gè)努力那樣編寫(xiě)的程序在其假定范圍之外使用時(shí)很快就會(huì)崩潰。 在其他國(guó)家/地區(qū)中,值123456.7可以設(shè)置為格式或鍵為"123.456,7" , "123456,7"或"123'456,7"或其他鍵。 假設(shè)所有區(qū)域設(shè)置都使用相同的分組分隔符和十進(jìn)制分隔符(同樣,在美國(guó)示例中分別使用“,”和“。”)的任何程序都將不起作用。 預(yù)料到此問(wèn)題,API包含java.text.NumberFormat 。 該類(lèi)提供了外部簡(jiǎn)單的parse()和format()方法,這些方法可以自動(dòng)進(jìn)行區(qū)域設(shè)置,包括格式化符號(hào)的知識(shí)。 實(shí)際上, NumberInput使用NumberFormat來(lái)格式化輸入字段中顯示的值。
Java Locale對(duì)象表示并標(biāo)識(shí)語(yǔ)言和地區(qū)或國(guó)家/地區(qū)的特定組合。 它本身不提供局部行為; 類(lèi)必須自己提供本地化。 但是,Java平臺(tái)確實(shí)支持一致的語(yǔ)言環(huán)境集,并且許多標(biāo)準(zhǔn)類(lèi)都實(shí)現(xiàn)一致的本地化行為。 這些類(lèi)通常具有兩種版本的方法:一種采用Locale參數(shù),而另一種采用默認(rèn)方法。 默認(rèn)語(yǔ)言環(huán)境在程序啟動(dòng)時(shí)自動(dòng)確定,或由傳遞給Java運(yùn)行時(shí)的參數(shù)覆蓋。
NumberFormat是一個(gè)抽象類(lèi),但它提供了靜態(tài)的工廠get XXX Instance()方法,用于獲取具有預(yù)定義的本地化格式的具體實(shí)現(xiàn)。 基礎(chǔ)實(shí)現(xiàn)通常是java.text.DecimalFormat的實(shí)例。 本文中的代碼和討論使用NumberFormat.getNumberInstance()返回的默認(rèn)值來(lái)格式化和解析雙NumberFormat.getIntegerInstance()值,使用NumberFormat.getIntegerInstance()來(lái)獲取整數(shù)值。
值得一提的是,完全本地化分析所需的代碼很少。 這些步驟是:
付出很少的努力的好處是巨大的,每個(gè)Java程序員都應(yīng)該使用NumberFormat來(lái)處理格式化的數(shù)字轉(zhuǎn)換。 要在不同的語(yǔ)言環(huán)境中進(jìn)行嘗試,請(qǐng)使用以下命令行調(diào)用NumberInput應(yīng)用程序,其中l(wèi)c是ISO-639語(yǔ)言代碼, cc是ISO-3166國(guó)家代碼:
java -Duser.language=lc -Duser.region=cc NumberInput從JDK 1.4開(kāi)始,可以使用user.country系統(tǒng)屬性代替user.region 。 要確定Java平臺(tái)支持的語(yǔ)言環(huán)境,請(qǐng)參閱JDK文檔的國(guó)際化部分中的支持的語(yǔ)言環(huán)境(請(qǐng)參閱參考資料 )。 程序可以使用java.util.Locale的靜態(tài)getAvailableLocales()方法在運(yùn)行時(shí)確定語(yǔ)言環(huán)境支持。
清單1顯示了NumberInput的NFInput()方法的相關(guān)代碼,單擊NF按鈕時(shí)將調(diào)用該代碼。 該方法使用NumberFormat.parse(String)進(jìn)行驗(yàn)證和轉(zhuǎn)換。
清單1. NFInput()方法使用NumberFormat.parse(String)
... NumberFormat nfDLocal = NumberFormat.getNumberInstance(),nfILocal = NumberFormat.getIntegerInstance(); ...public void NFInput( String sDouble, String sInt ){ // "standard" NumberFormat parsingdouble d;int i;Number n;try{n = nfDLocal.parse( sDouble );d = n.doubleValue();...n = nfILocal.parse( sInt );i = n.intValue();...}catch( ParseException pe ) { ...}} // end NFInputNumberFormat實(shí)例的實(shí)現(xiàn)
在這一點(diǎn)上,簡(jiǎn)要回顧一下NumberFormat被要求get XXX Instance()時(shí)發(fā)生的情況以及DecimalFormatSymbols類(lèi)的角色都是有用的。 討論基于對(duì)J2SE 1.4附帶的參考實(shí)現(xiàn)源代碼的回顧,并且可能會(huì)發(fā)生變化。
事件的基本流程是NumberFormat基于關(guān)聯(lián)的語(yǔ)言環(huán)境向內(nèi)部ListResourceBundle咨詢適當(dāng)?shù)哪J?#xff0c;并返回使用該模式創(chuàng)建的DecimalFormat對(duì)象。 如果沒(méi)有顯式的負(fù)模式,則將正負(fù)號(hào)與正模式組合使用。 在此過(guò)程中,將創(chuàng)建適合區(qū)域設(shè)置的DecimalFormatSymbols對(duì)象,并且DecimalFormat實(shí)例將獲得對(duì)該對(duì)象的引用。 因?yàn)镹umberFormat.get XXX Instance()方法基于工廠模式,所以其他實(shí)現(xiàn)或?qū)?lái)的引用實(shí)現(xiàn)可能返回不同的類(lèi)。 因此,任何自定義代碼必須確保DecimalFormat嘗試訪問(wèn)相關(guān)的前實(shí)際返回DecimalFormatSymbols實(shí)例。
DecimalFormatSymbols對(duì)象包含信息,例如適當(dāng)?shù)氖M(jìn)制和分組分隔符以及減號(hào)。 單擊“信息”按鈕時(shí), NumberInput收集大量此類(lèi)信息并將其顯示在對(duì)話框中。 圖3顯示了使用en_US語(yǔ)言環(huán)境的示例。 此信息對(duì)于解析和驗(yàn)證本地化格式的數(shù)字至關(guān)重要。
圖3. DecimalFormatSymbols數(shù)據(jù)
嘗試單擊NF按鈕,您將看到即使使用逗號(hào)或其他本地分組分隔符也可以正確接受這些值。 根據(jù)當(dāng)前樣式放置減號(hào)也可以接受。 減號(hào)在另一個(gè)位置時(shí)該怎么辦? 這以及其他幾個(gè)問(wèn)題是下一節(jié)的主題,也是本文的動(dòng)力。
UnexpectedResults.equals(bigTrouble)
關(guān)于Java國(guó)際化的大多數(shù)文章都將重點(diǎn)放在NumberFormat的格式化功能上,并在到目前為止我給出的信息有所變化之后結(jié)束對(duì)解析的任何討論。 不幸的是,對(duì)該類(lèi)(實(shí)際上是從NumberFormat.get XXX Instance()返回的具體DecimalFormat子類(lèi))進(jìn)行的測(cè)試和實(shí)驗(yàn)顯示了解析異常,這可能令人驚訝:在許多常見(jiàn)的字段條件下, NumberFormat.parse(String)欣喜地截?cái)鄶?shù)據(jù)并在沒(méi)有向程序員指示的情況下丟失信號(hào)。 以下情況顯示了此行為(除非另有說(shuō)明,否則使用en_US語(yǔ)言環(huán)境):
- 十進(jìn)制分隔符之前的多個(gè)連續(xù)或不規(guī)則插入的分組分隔符將被忽略。
例如, "123,,,456.7" "123,45,6.7"和"123,45,6.7"被接受,并且都返回123456.7 。
經(jīng)過(guò)深思熟慮,我得出的結(jié)論是,盡管從技術(shù)上講,這種行為是錯(cuò)誤的,但不會(huì)丟失任何數(shù)據(jù),任何解決方案都會(huì)導(dǎo)致超出其價(jià)值的工作。 您應(yīng)該了解該行為,但是NumberInput應(yīng)用程序無(wú)法糾正它,并且在本文中我將不再對(duì)其進(jìn)行詳細(xì)介紹。 - 在十進(jìn)制分隔符之后出現(xiàn)的分組分隔符會(huì)導(dǎo)致截?cái)唷?/strong>
"123,456.7,85"被接受為123456.7 。 - 多個(gè)十進(jìn)制分隔符會(huì)導(dǎo)致截?cái)唷?/strong>
"123,456..7"被接受為123456.0 ; "12.3.456.7"被接受為12.3 。 - 對(duì)于帶有前減號(hào)(負(fù)前綴)的模式,截?cái)鄷?huì)在非數(shù)字字符的點(diǎn)處發(fā)生,包括嵌入的負(fù)號(hào)。
"123,4r56.7"被接受為1234.0 ; "12-3,456.7"被接受為12.0 (正值)。 - 對(duì)于帶有尾隨減號(hào)(負(fù)后綴)的模式,截?cái)鄷?huì)在非數(shù)字字符的點(diǎn)處發(fā)生,不包括嵌入的減號(hào)。 可接受嵌入的負(fù)號(hào),但任何其他數(shù)據(jù)都將被截?cái)唷?/strong>
對(duì)于沙特阿拉伯語(yǔ)言環(huán)境( ar_SA ), "123,4r56.7"被接受為1234.0 ; 接受"12-3,456.7"作為-12.0 (負(fù)值)。 - 如果模式為負(fù)輸入指定前導(dǎo)負(fù)號(hào),則尾隨負(fù)號(hào)將被忽略。
接受"123,456.7-"作為123456.7 (正值),接受"-123.456,7-" (荷蘭語(yǔ)區(qū)域設(shè)置nl_NL )作為-123456.7 (負(fù)值)。
圖4和圖5顯示了單擊NF按鈕時(shí)其中一些行為的示例。 盡管可能難以解釋原始條目的意圖,但可以肯定的是,沒(méi)有預(yù)料到會(huì)出現(xiàn)1234.0的雙重結(jié)果,用戶也不想從整數(shù)輸入中刪除最后兩位。 同樣,不會(huì)引發(fā)異常,也沒(méi)有跡象表明輸入的部分被忽略了。
圖4. NumberFormat.parse(String)的意外結(jié)果
圖5. NumberFormat.parse(String)接受截?cái)嗟闹?
考慮到實(shí)現(xiàn)NumberFormat和DecimalFormat類(lèi)所需的工作量,這些結(jié)果在許多使用JDK 1.4和5.0進(jìn)行的測(cè)試中都是一致的。 另一方面,代碼比將參數(shù)傳遞給方法并檢查結(jié)果要簡(jiǎn)單得多。 唯一的真實(shí)線索是在NumberFormat.parse(String source)的JDK文檔中,該文檔沒(méi)有進(jìn)一步說(shuō)明就說(shuō):“該方法可能不會(huì)使用給定字符串的整個(gè)文本。”
看起來(lái)像這樣的異常是很麻煩的,乍一看,似乎最好返回編程的“按自己的方式來(lái)做”。 “垃圾進(jìn),垃圾出”在計(jì)算領(lǐng)域是老生常談,但這僅意味著程序無(wú)法保證數(shù)據(jù)正確無(wú)誤 。 程序員的義務(wù)是盡可能確保所有輸入均有效 。 與其說(shuō)它是一個(gè)錯(cuò)誤,不如說(shuō)是一種NumberFormat.parse(String)的設(shè)計(jì),它盡可能地從輸入字符串的某個(gè)部分返回一個(gè)數(shù)字。 不幸的是,該行為包括一個(gè)未聲明的假設(shè),即數(shù)據(jù)已經(jīng)通過(guò)驗(yàn)證。 最終結(jié)果是程序員無(wú)法確定何時(shí)輸入無(wú)效,這破壞了與用戶和數(shù)據(jù)本身的隱式契約。
幾年前發(fā)現(xiàn)這些問(wèn)題時(shí),我的第一React是為parse(String)方法編寫(xiě)相當(dāng)于前端預(yù)處理器的內(nèi)容。 那行得通,但是代價(jià)是額外的,部分冗余的代碼和更多的時(shí)間來(lái)處理數(shù)據(jù)。 幸運(yùn)的是,事實(shí)證明,謹(jǐn)慎使用現(xiàn)有的NumberFormat方法可以解決此問(wèn)題。
使用ParsePosition進(jìn)行驗(yàn)證
parse(String source, ParsePosition parsePosition)方法是不尋常的,因?yàn)樗粫?huì)引發(fā)任何異常。 它通常用于從單個(gè)字符串中解析多個(gè)數(shù)字時(shí)使用。 但是,返回方法時(shí), ParsePosition.getIndex()的值是輸入字符串中最后一個(gè)解析的位置加一個(gè)。 如果代碼始終以索引設(shè)置為零開(kāi)始,則在處理后,索引值將等于已解析字符的數(shù)量。 使用驗(yàn)證方法的關(guān)鍵是將更新后的索引與原始輸入字符串的長(zhǎng)度進(jìn)行比較。
為避免混淆,我應(yīng)該提到ParsePosition也有一個(gè)getErrorIndex()方法。 此方法對(duì)于此處討論的條件基本上沒(méi)有用,因?yàn)闆](méi)有檢測(cè)到錯(cuò)誤。 另外,在使用它時(shí),必須在每次解析操作之前將錯(cuò)誤索引重置為-1; 否則結(jié)果可能會(huì)產(chǎn)生誤導(dǎo)。
單擊NF或NFPP按鈕時(shí), NumberInput應(yīng)用程序?qū)⒃贚ength / PP列下顯示ParsePosition索引。 如果原始值的長(zhǎng)度大于零且與索引值匹配,則兩者均顯示為綠色;否則,兩者均顯示為綠色。 否則,這些值將顯示為紅色。 此操作與特定的驗(yàn)證方法分開(kāi)完成。 如果再次查看圖4 ,即使與NF按鈕關(guān)聯(lián)的NFInput()方法接受了數(shù)據(jù),該值也將顯示為紅色,表明存在錯(cuò)誤。
對(duì)于最終的驗(yàn)證版本,當(dāng)NFPPInput() NFPP按鈕時(shí),將調(diào)用NFPPInput()方法。 此方法使用parse(String, ParsePosition)驗(yàn)證輸入并獲取數(shù)字值。 圖6和圖7顯示在NFPPInput()檢測(cè)到來(lái)自圖4的無(wú)效輸入。 在我的測(cè)試中,該方法正確處理了NumberFormat.parse(String)遺漏的所有條件。
圖6.檢測(cè)無(wú)效的重復(fù)條目
圖7.檢測(cè)無(wú)效的整數(shù)條目
您必須遵循一些準(zhǔn)則,以確保使用parse(String, ParsePosition)正確的結(jié)果:
- 請(qǐng)記住,該方法永遠(yuǎn)不會(huì)引發(fā)異常。
為了清楚和演示起見(jiàn),此處的代碼僅顯示“ 可接受 / 不可接受”對(duì)話框。 在通用情況下,應(yīng)該拋出ParseException使其更符合正常期望。 - 始終在調(diào)用parse(String, ParsePosition)之前將ParsePosition索引重置為零。
必須進(jìn)行重置,因?yàn)槭褂么朔椒?#xff0c;解析ParsePosition輸入字符串中的ParsePosition索引開(kāi)始。 - 使用NumberFormat.getNumberInstance()解析雙NumberFormat.getIntegerInstance()值,使用NumberFormat.getIntegerInstance()解析整數(shù)值。
如果您不對(duì)整數(shù)使用整數(shù)實(shí)例(或者將setParseIntegerOnly(true)應(yīng)用于數(shù)字實(shí)例),則該方法將解析所有小數(shù)點(diǎn)分隔符,直到輸入字符串的末尾。 結(jié)果是長(zhǎng)度和索引匹配,并且您接受了無(wú)效的輸入。 - 除了比較長(zhǎng)度和索引值是否相等之外,還必須在解析后檢查是否為空Number或輸入字符串為空(“”或長(zhǎng)度為零)。
清除輸入字段將導(dǎo)致一個(gè)空字符串。 在這種情況下,長(zhǎng)度和索引值均為零,因此它們匹配。 對(duì)于空字符串輸入,parse方法返回null。 此行為與使用NumberFormat.parse(String source)空字符串的結(jié)果不同,后者會(huì)拋出“無(wú)法解析的數(shù)字” ParseException 。 請(qǐng)記住, parse(String source, ParsePosition parsePosition)永遠(yuǎn)不會(huì)引發(fā)異常! 在NumberInput ,清單2中的代碼段用于處理各種可能性:清單2.檢查錯(cuò)誤情況
if( sDouble.length() != pp.getIndex() || n == null ) { /* error */ }
總而言之,正確輸入處理的步驟為:
清單3顯示了相關(guān)代碼:
清單3. NFPPInput()方法
... NumberFormat nfDLocal = NumberFormat.getNumberInstance(), nfILocal = NumberFormat.getIntegerInstance();ParsePosition pp; ...public void NFPPInput( String sDouble, String sInt ){ // validate NumberFormat with ParsePosition Number n;double d;int i;pp.setIndex( 0 );n = nfDLocal.parse( sDouble, pp );if( sDouble.length() != pp.getIndex() || n == null ){showErrorMsg( "Double Input Not Acceptable\n" + "\"" + sDouble + "\"");}else{d = n.doubleValue();jtD.setText( nfDLocal.format( d ) );showInfoMsg( "Double Accepted \n" + d );}pp.setIndex( 0 );n = nfILocal.parse( sInt, pp );if( sInt.length() != pp.getIndex() || n == null ){showErrorMsg( "Int Input Not Acceptable \n" + "\"" + sInt + "\"");}else{i = n.intValue();jtI.setText( nfILocal.format( i ) );showInfoMsg( "Int Accepted \n" + i );}} // end NFPPInput結(jié)論
Java SE API中已進(jìn)行了大量工作,不僅允許在字節(jié)碼級(jí)別“寫(xiě)一次,在任何地方運(yùn)行”,而且還可以容納國(guó)際化和本地化的應(yīng)用程序。 NumberFormat和DecimalFormat是打算編寫(xiě)世界一流應(yīng)用程序的Java程序員不能沒(méi)有的類(lèi)。 但是,如本文所示,開(kāi)發(fā)人員也無(wú)法使用parse(String source)方法,除非可以假定完美的輸入-在現(xiàn)實(shí)世界中很少出現(xiàn)這種情況。 我在本文中提供的信息和代碼為您提供了另一種使用parse(String source, ParsePosition parsePosition)來(lái)確定條目何時(shí)無(wú)效并獲得正確結(jié)果的技術(shù)。
翻譯自: https://www.ibm.com/developerworks/java/library/j-numberformat/index.html
總結(jié)
以上是生活随笔為你收集整理的numberformat_解决NumberFormat的解析问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: FTP协议及工作原理
- 下一篇: 程序人生:什么是“对用户友好”