改进java字符串分解的方法

上传人:ji****n 文档编号:45995656 上传时间:2018-06-20 格式:DOC 页数:3 大小:36KB
返回 下载 相关 举报
改进java字符串分解的方法_第1页
第1页 / 共3页
改进java字符串分解的方法_第2页
第2页 / 共3页
改进java字符串分解的方法_第3页
第3页 / 共3页
亲,该文档总共3页,全部预览完了,如果喜欢就下载吧!
资源描述

《改进java字符串分解的方法》由会员分享,可在线阅读,更多相关《改进java字符串分解的方法(3页珍藏版)》请在金锄头文库上搜索。

1、改进 JAVA 字符串分解的方法(转) 2008 年 12 月 19 日 星期五 11:27 一、概述 大多数 Java 程序员都曾经使用过 java.util.StringTokenizer 类。 它是一个很方便的字符串分解器,主要用来根据分隔符把字符串分割成标记 (Token),然后按照请求返回各个标记。这个过程称为 Tokenization,实际上就 是把字符序列转换成应用程序能够理解的多个标记。 虽然 StringTokenizer 用起来很方便,但它的功能却很有限。这个类只是简单地在输入字符串中查找分隔 符,一旦找到了分隔符就分割字符串。它不会检查分隔符是否在子串之中这类条件, 当输

2、入字符串中出现两个连续的分隔符时,它也不会返回“(字符串长度为 0)形 式的标记。为了突破这些局限,Java 2 平台提供了 BreakIterator 类,它是在 StringTokenizer 之上改进的字符串分解器。由于 JDK 1.1.x 没有提供这个类,为 了满足自己的需要,开发者经常花费很多时间从头开始编写分解器。在涉及到数据 格式化处理的大型工程中,这类定制的字符串分解器有时随处可见,而且这种情况 并不罕见。 本文的目标是帮助你利用现有的 StringTokenizer 类,编写一个高级字符串分解器。二、StringTokenizer 的局限 你可以用以下三种构造函数中的任意一种

3、创建 StringTokenizer 分解器:StringTokenizer(String sInput):以空白字符(“ ”,“t”,“n”)为分 隔符分割字符串。StringTokenizer(String sInput, String sDelimiter):以 sDelimiter 为分隔符 分割字符串。StringTokenizer(String sInput, String sDelimiter, boolean bReturnTokens): 以 sDelimiter 为分隔符分割字符串,但如果 bReturnTokens 为 true,则分隔符也 作为标记返回。 第一个构造函数

4、不检查输入字符串是否包含子串。例如,如果以空白字符为分 隔符分割“hello. Today “I am “ going to my home town”,则字符串分解结 果是 hello.、Today、“I、am、“、going 等,而不是 hello.、Today、“I am “、going 等。 第二个构造函数不检查两个分隔符连续出现的情况。例如,如果以“,”为分隔 符分割“book, author, publication,date published”这个字符串,则 StringTokenizer 返回 book、author、publication 和 date published

5、这四个标记, 而不是 book、author、publication、“、“和 date published 这 6 个标记(其中 “表示 0 长度字符串)。要得到 6 个标记的答案,你必须把 StringTokenizer 的 bReturnTokens 参数设置为 true。 允许设置值为 true 的 bReturnTokens 参数是一个重要的功能,因为它考虑到了分隔符连续出现的情况。例如,使用第二个构 造函数时,如果数据是动态收集得到而且要用来更新数据库中的表,输入字符串中 的标记对应着表里面列的值,那么当我们不能确定哪一个列应该设置为“时,我们 就无法把输入串中的标记映射到数据库列

6、。假设我们要把记录插入到一个有 6 个列 的表,而输入数据中包含两个连续的分隔符。此时,StringTokenizer 的分解结果 是 5 个标记(两个连续的分隔符代表“标记,它将被 StringTokenizer 忽略),而 我们却有 6 个字段需要设置。同时,我们也不知道连续分隔符在哪里出现,所以也 就不知道哪一个列应该设置成“。 当标记本身等同于分隔符(无论是长度还是值)且位于子串之内时,第三个构造函 数无效。例如,如果我们要以“,”为分隔符分解字符串“book, author, publication,“,“,date published”(这个字符串包含一个“,”标记,它与分 隔符一

7、样),结果是 book、author、publication、“、“、date published 这六个 标记,而不是 book、author、publication、,(逗号字符)、date published 这 五个标记。再提醒一下,即使我们把 StringTokenizer 的 bReturnTokens 参数设置 设置成了 true,在这种情况下也没有什么帮助。三、高级字符串分解器 在编写代码之前,你必须搞清楚一个好的分解器有哪 些基本要求。因为 Java 开发者已经习惯于使用 StringTokenizer 类,所以一个好 的分解器应该提供 StringTokenizer 类提供

8、的所有实用方法,比如 hasMoreTokens()、nextToken()、countTokens()。 本文提供的代码很简单,而且大部分代码足以自我解释。在这里,我主要利用了 StringTokenizer 类(创建类实例时 bReturnTokens 参数设置为 true),并提供了 上面提到的几个方法。大多数时候标记与分隔符不同,有些时候分隔符却要作为标 记输出(尽管非常罕见),此时如果出现了对标记的请求,分解器要把分隔符作为 标记输出。创建 PowerfulTokenizer 对象时,你只需要提供输入字符串和分隔符这 两个参数,PowerfulTokenizer 将在内部使用 bRe

9、turnTokens 设置成 true 的 StringTokenizer。(这么做的原因在于,如果不是用 bReturnTokens 设置成 true 的方式创建 StringTokenizer,那么它将在解决先前提出的问题时受到限制)。为 了正确地控制分解器,代码在几个地方(计算标记的总数量以及 nextToken())检 查 bReturnTokens 是否设置成了 true。 你可能已经发现,PowerfulTokenizer 实现了 Enumeration 接口,从而也就实现了 hasMoreElements()和 nextElement() 这两个方法,而这两个方法又分别把调用直接

10、委托给 hasMoreTokens()和 nextToken()。(由于实现了 Enumeration 接口,PowerfulTokenizer 实现了与 StringTokenizer 的向后兼容。) 我们来看一个例子,假设输入字符串是“hello, Today, “I, am “, going to, “buy, a, book“”,分隔符是“,”。用分解器分割这个字符串时返回结 果如表 1 所示: 表 1:字符串分解结果 输入字符串包含 11 个逗号(,)字符, 其中 3 个在子串里面、4 个连续出现(“Today,”中包含两个连续逗号,第一个 逗号是 Today 的分隔符)。下面是 P

11、owerfulTokenizer 计算标记总数的算法: 如 果 bReturnTokens=true,把子串中的分隔符数量乘以 2,再从实际总数量减去该数 字,就得到了标记的总数。理由是,对于子串“buy, a, book”, StringTokenizer 将返回 5 个标记(即“buy:,:a:,:book”),而PowerfulTokenizer 将返回一个标记(即“buy, a, book”),两者的差值是 4(即,2 乘以子串中的分隔符数量)。这个公式对于所有包含分隔符的子串都有效。类似地,对于 bReturnTokens=false 的情形,我们从实际总数(19)减去表达式 分隔符

12、总数(11)- 连续分隔符数量(4) + 子串中的分隔符数量(3)。由于 这时我们不返回分隔符,它们(非连续出现或在子串内部)对我们来说没有用,上 面的公式为我们返回了标记的总数量(9)。 请记住这两个公式,它们是 PowerfulTokenizer 的核心。这两个公式适用于几乎所有它们各自条件下的情形。 但是,如果你有更复杂的要求,不能使用这两个公式,那么你应该在编写代码之前 分析各种可能出现的情况,并设计出自己的公式。 / 检查分隔符是否位于子串之 内 for (int i=1; i/td iIndex = sInput.indexOf(sDelim, iIndex+1); if (iIn

13、dex = -1) break; / 如果分隔符 位于子串之内,则向前分析直至子串结束 while (sInput.substring(iIndex- iLen, iIndex).equals(sDelim) iNextIndex = sInput.indexOf(sDelim, iIndex+1); if (iNextIndex = -1) break; iIndex = iNextIndex; aiIndexi = iIndex; /System.out.println(“aiIndex“ + i + “ = “ + iIndex); if (isWithinQuotes(iIndex)

14、if (bIncludeDelim) iTokens -= 2; else iTokens -= 1; countTokens()方法检查子串是否包含双引号。如果包含,那么它减少总数并把索 引值修改为字符串中下一个双引号出现的位置(如上面的代码片断所示)。如果 bReturnTokens 是 false,那么它从总数减去输入字符串中出现的非连续分隔符的 数量。 / 如发现多个连续的分隔符,则返回“作为标记 if ( (sPrevToken.equals(sDelim) iTokenNo+; return “; / 检查标记本身是否等于分隔符 if ( (sToken.trim().starts

15、With(“) while (!sNextToken sToken += sNextToken; sPrevToken = sToken; iTokenNo+; return sToken.substring(1, sToken.length()-1); / 检查字符串中是否包含 子串 else if ( (sToken.trim().startsWith(“) / 检查“ while (!(sNextToken.trim(). endsWith(“) if (!oTokenizer.hasMoreTokens() sNextToken = “; break; sNextToken = oTo

16、kenizer.nextToken(); sToken += sNextToken; nextToken()方法通过 StringTokenizer.nextToken 方法获取标记,并检查标记中 的双引号字符。如果发现了这些字符,它继续获取标记直至不能再找到带有双引号 的标记。另外,它还把标记保存到一个变量(sPrevToken,参见本文后面完整的源 代码)以检查连续出现的分隔符。如果 nextToken()发现等同于分隔符的连续多个 标记,那么它返回“(长度为 0 的字符串)作为标记。 按照类似的方法, hasMoreTokens()方法检查已经返回的标记数量是否小于标记的总数量。 本文 为你介绍了如何轻松地编写一个强大的字符串分解器。根据本文介绍的原理,你能 够迅速编写出复杂的字符串分解器,节省

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号