免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
改進(jìn)java字符串分解的方法
一、概述

  大多數(shù)Java程序員都曾經(jīng)使用過java.util.StringTokenizer類。它是一個很方便的字符串分解器,主要用來根據(jù)分隔符把字符串分割成標(biāo)記(Token),然后按照請求返回各個標(biāo)記。這個過程稱為Tokenization,實際上就是把字符序列轉(zhuǎn)換成應(yīng)用程序能夠理解的多個標(biāo)記。

  雖然StringTokenizer用起來很方便,但它的功能卻很有限。這個類只是簡單地在輸入字符串中查找分隔符,一旦找到了分隔符就分割字符串。它不會檢查分隔符是否在子串之中這類條件,當(dāng)輸入字符串中出現(xiàn)兩個連續(xù)的分隔符時,它也不會返回""(字符串長度為0)形式的標(biāo)記。

  為了突破這些局限,Java 2平臺提供了BreakIterator類,它是在StringTokenizer之上改進(jìn)的字符串分解器。由于JDK 1.1.x沒有提供這個類,為了滿足自己的需要,開發(fā)者經(jīng)?;ㄙM很多時間從頭開始編寫分解器。在涉及到數(shù)據(jù)格式化處理的大型工程中,這類定制的字符串分解器有時隨處可見,而且這種情況并不罕見。

  本文的目標(biāo)是幫助你利用現(xiàn)有的StringTokenizer類,編寫一個高級字符串分解器。

二、StringTokenizer的局限

  你可以用以下三種構(gòu)造函數(shù)中的任意一種創(chuàng)建StringTokenizer分解器:


StringTokenizer(String sInput):以空白字符(“ ”,“\t”,“\n”)為分隔符分割字符串。
StringTokenizer(String sInput, String sDelimiter):以sDelimiter為分隔符分割字符串。
StringTokenizer(String sInput, String sDelimiter, boolean bReturnTokens):以sDelimiter為分隔符分割字符串,但如果bReturnTokens為true,則分隔符也作為標(biāo)記返回。
  第一個構(gòu)造函數(shù)不檢查輸入字符串是否包含子串。例如,如果以空白字符為分隔符分割“hello. Today \"I am \" going to my home town”,則字符串分解結(jié)果是hello.、Today、"I、am、"、going等,而不是hello.、Today、"I am "、going等。

  第二個構(gòu)造函數(shù)不檢查兩個分隔符連續(xù)出現(xiàn)的情況。例如,如果以“,”為分隔符分割“book, author, publication,,,date published”這個字符串,則StringTokenizer返回book、author、publication和date published這四個標(biāo)記,而不是book、author、publication、""、""和date published這6個標(biāo)記(其中""表示0長度字符串)。要得到6個標(biāo)記的答案,你必須把StringTokenizer的bReturnTokens參數(shù)設(shè)置為true。

  允許設(shè)置值為true的bReturnTokens參數(shù)是一個重要的功能,因為它考慮到了分隔符連續(xù)出現(xiàn)的情況。例如,使用第二個構(gòu)造函數(shù)時,如果數(shù)據(jù)是動態(tài)收集得到而且要用來更新數(shù)據(jù)庫中的表,輸入字符串中的標(biāo)記對應(yīng)著表里面列的值,那么當(dāng)我們不能確定哪一個列應(yīng)該設(shè)置為""時,我們就無法把輸入串中的標(biāo)記映射到數(shù)據(jù)庫列。假設(shè)我們要把記錄插入到一個有6個列的表,而輸入數(shù)據(jù)中包含兩個連續(xù)的分隔符。此時,StringTokenizer的分解結(jié)果是5個標(biāo)記(兩個連續(xù)的分隔符代表""標(biāo)記,它將被StringTokenizer忽略),而我們卻有6個字段需要設(shè)置。同時,我們也不知道連續(xù)分隔符在哪里出現(xiàn),所以也就不知道哪一個列應(yīng)該設(shè)置成""。

  當(dāng)標(biāo)記本身等同于分隔符(無論是長度還是值)且位于子串之內(nèi)時,第三個構(gòu)造函數(shù)無效。例如,如果我們要以“,”為分隔符分解字符串“book, author, publication,\",\",date published”(這個字符串包含一個“,”標(biāo)記,它與分隔符一樣),結(jié)果是book、author、publication、"、"、date published這六個標(biāo)記,而不是book、author、publication、,(逗號字符)、date published這五個標(biāo)記。再提醒一下,即使我們把StringTokenizer的bReturnTokens參數(shù)設(shè)置設(shè)置成了true,在這種情況下也沒有什么幫助。

三、高級字符串分解器

  在編寫代碼之前,你必須搞清楚一個好的分解器有哪些基本要求。因為Java開發(fā)者已經(jīng)習(xí)慣于使用StringTokenizer類,所以一個好的分解器應(yīng)該提供StringTokenizer類提供的所有實用方法,比如hasMoreTokens()、nextToken()、countTokens()。

  本文提供的代碼很簡單,而且大部分代碼足以自我解釋。在這里,我主要利用了StringTokenizer類(創(chuàng)建類實例時bReturnTokens參數(shù)設(shè)置為true),并提供了上面提到的幾個方法。大多數(shù)時候標(biāo)記與分隔符不同,有些時候分隔符卻要作為標(biāo)記輸出(盡管非常罕見),此時如果出現(xiàn)了對標(biāo)記的請求,分解器要把分隔符作為標(biāo)記輸出。創(chuàng)建PowerfulTokenizer對象時,你只需要提供輸入字符串和分隔符這兩個參數(shù),PowerfulTokenizer將在內(nèi)部使用bReturnTokens設(shè)置成true的StringTokenizer。(這么做的原因在于,如果不是用bReturnTokens設(shè)置成true的方式創(chuàng)建StringTokenizer,那么它將在解決先前提出的問題時受到限制)。為了正確地控制分解器,代碼在幾個地方(計算標(biāo)記的總數(shù)量以及nextToken())檢查bReturnTokens是否設(shè)置成了true。

  你可能已經(jīng)發(fā)現(xiàn),PowerfulTokenizer實現(xiàn)了Enumeration接口,從而也就實現(xiàn)了hasMoreElements()和nextElement()這兩個方法,而這兩個方法又分別把調(diào)用直接委托給hasMoreTokens()和nextToken()。(由于實現(xiàn)了Enumeration接口,PowerfulTokenizer實現(xiàn)了與StringTokenizer的向后兼容。)

  我們來看一個例子,假設(shè)輸入字符串是“hello, Today,,, \"I, am \", going to,,, \"buy, a, book\"”,分隔符是“,”。用分解器分割這個字符串時返回結(jié)果如表1所示:

表1:字符串分解結(jié)果

  輸入字符串包含11個逗號(,)字符,其中3個在子串里面、4個連續(xù)出現(xiàn)(“Today,,,”中包含兩個連續(xù)逗號,第一個逗號是Today的分隔符)。下面是PowerfulTokenizer計算標(biāo)記總數(shù)的算法:


如果bReturnTokens=true,把子串中的分隔符數(shù)量乘以2,再從實際總數(shù)量減去該數(shù)字,就得到了標(biāo)記的總數(shù)。理由是,對于子串“buy, a, book”,StringTokenizer將返回5個標(biāo)記(即“buy:,:a:,:book”),而PowerfulTokenizer將返回一個標(biāo)記(即“buy, a, book”),兩者的差值是4(即,2乘以子串中的分隔符數(shù)量)。這個公式對于所有包含分隔符的子串都有效。
類似地,對于bReturnTokens=false的情形,我們從實際總數(shù)(19)減去表達(dá)式[分隔符總數(shù)(11)- 連續(xù)分隔符數(shù)量(4) + 子串中的分隔符數(shù)量(3)]。由于這時我們不返回分隔符,它們(非連續(xù)出現(xiàn)或在子串內(nèi)部)對我們來說沒有用,上面的公式為我們返回了標(biāo)記的總數(shù)量(9)。
  請記住這兩個公式,它們是PowerfulTokenizer的核心。這兩個公式適用于幾乎所有它們各自條件下的情形。但是,如果你有更復(fù)雜的要求,不能使用這兩個公式,那么你應(yīng)該在編寫代碼之前分析各種可能出現(xiàn)的情況,并設(shè)計出自己的公式。


// 檢查分隔符是否位于子串之內(nèi)
for (int i=1; i<aiIndex.length; i++)>/td>
{
iIndex = sInput.indexOf(sDelim, iIndex+1);
if (iIndex == -1)
break;
// 如果分隔符位于子串之內(nèi),則向前分析直至子串結(jié)束
while (sInput.substring(iIndex-iLen, iIndex).equals(sDelim))
{
iNextIndex = sInput.indexOf(sDelim, iIndex+1);
if (iNextIndex == -1)
break;
iIndex = iNextIndex;
}
aiIndex[i] = iIndex;
//System.out.println("aiIndex[" + i + "] = " + iIndex);
if (isWithinQuotes(iIndex))
{
if (bIncludeDelim)
iTokens -= 2;
else
iTokens -= 1;
}
}




  countTokens()方法檢查子串是否包含雙引號。如果包含,那么它減少總數(shù)并把索引值修改為字符串中下一個雙引號出現(xiàn)的位置(如上面的代碼片斷所示)。如果bReturnTokens是false,那么它從總數(shù)減去輸入字符串中出現(xiàn)的非連續(xù)分隔符的數(shù)量。


// 如發(fā)現(xiàn)多個連續(xù)的分隔符,則返回""作為標(biāo)記
if ( (sPrevToken.equals(sDelim)) && (sToken.equals(sDelim)) ) {
sPrevToken = sToken;
iTokenNo++;
return "";
}

// 檢查標(biāo)記本身是否等于分隔符
if ( (sToken.trim().startsWith("\"")) && (sToken.length() == 1) ) {
// 標(biāo)記本身等于分隔符的特殊情況
String sNextToken = oTokenizer.nextToken();
while (!sNextToken
sToken += sNextToken;
sPrevToken = sToken;
iTokenNo++;
return sToken.substring(1, sToken.length()-1);
}
// 檢查字符串中是否包含子串
else if ( (sToken.trim().startsWith("\""))
&& (!((sToken.trim().endsWith("\""))
&& (!sToken.trim().endsWith("\"\"")))) )
{
if (oTokenizer.hasMoreTokens())
{
String sNextToken = oTokenizer.nextToken();
// 檢查"\"\""
while (!((sNextToken.trim().endsWith("\""))
&& (!sNextToken.trim().endsWith("\"\""))) )
{
sToken += sNextToken;
if (!oTokenizer.hasMoreTokens())
{
sNextToken = "";
break;
}
sNextToken = oTokenizer.nextToken();
}
sToken += sNextToken;
}
}
  nextToken()方法通過StringTokenizer.nextToken方法獲取標(biāo)記,并檢查標(biāo)記中的雙引號字符。如果發(fā)現(xiàn)了這些字符,它繼續(xù)獲取標(biāo)記直至不能再找到帶有雙引號的標(biāo)記。另外,它還把標(biāo)記保存到一個變量(sPrevToken,參見本文后面完整的源代碼)以檢查連續(xù)出現(xiàn)的分隔符。如果nextToken()發(fā)現(xiàn)等同于分隔符的連續(xù)多個標(biāo)記,那么它返回""(長度為0的字符串)作為標(biāo)記。

  按照類似的方法,hasMoreTokens()方法檢查已經(jīng)返回的標(biāo)記數(shù)量是否小于標(biāo)記的總數(shù)量。

  【結(jié)束語】本文為你介紹了如何輕松地編寫一個強大的字符串分解器。根據(jù)本文介紹的原理,你能夠迅速編寫出復(fù)雜的字符串分解器,節(jié)省大量的開發(fā)時間
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
如何輕松編寫一個強大的字符串分解器(2)
Java將一段逗號分割的字符串轉(zhuǎn)換成一個數(shù)組
java版本號與別名
Java 發(fā)展簡史
JavaScript常用String對象方法和Math對象屬性集 - uoik開發(fā)網(wǎng)
java.util.StringTokenizer
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服