选择显示字体大小

如何轻松编写一个强大的字符串分解器

一、概述

大多数java程序员都曾经使用过java.util.stringtokenizer类。它是一个很方便的字符串分解器,主要用来根据分隔符把字符串分割成标记(token),然后按照请求返回各个标记。这个过程称为tokenization,实际上就是把字符序列转换成应用程序能够理解的多个标记。

虽然stringtokenizer用起来很方便,但它的功能却很有限。这个类只是简单地在输入字符串中查找分隔符,一旦找到了分隔符就分割字符串。它不会检查分隔符是否在子串之中这类条件,当输入字符串中出现两个连续的分隔符时,它也不会返回""(字符串长度为0)形式的标记。

为了突破这些局限,java 2平台提供了breakiterator类,它是在stringtokenizer之上改进的字符串分解器。由于jdk 1.1.x没有提供这个类,为了满足自己的需要,开发者经常花费很多时间从头开始编写分解器。在涉及到数据格式化处理的大型工程中,这类定制的字符串分解器有时随处可见,而且这种情况并不罕见。

本文的目标是帮助你利用现有的stringtokenizer类,编写一个高级字符串分解器。

二、stringtokenizer的局限

你可以用以下三种构造函数中的任意一种创建stringtokenizer分解器:

stringtokenizer(string sinput):以空白字符( ,\t,\n)为分隔符分割字符串。

stringtokenizer(string sinput, string sdelimiter):以sdelimiter为分隔符分割字符串。

stringtokenizer(string sinput, string sdelimiter, boolean breturntokens):以sdelimiter为分隔符分割字符串,但如果breturntokens为true,则分隔符也作为标记返回。

第一个构造函数不检查输入字符串是否包含子串。例如,如果以空白字符为分隔符分割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这四个标记,而不是book、author、publication、""、""和date published这6个标记(其中""表示0长度字符串)。要得到6个标记的答案,你必须把stringtokenizer的breturntokens参数设置为true。

允许设置值为true的breturntokens参数是一个重要的功能,因为它考虑到了分隔符连续出现的情况。例如,使用第二个构造函数时,如果数据是动态收集得到而且要用来更新数据库中的表,输入字符串中的标记对应着表里面列的值,那么当我们不能确定哪一个列应该设置为""时,我们就无法把输入串中的标记映射到数据库列。假设我们要把记录插入到一个有6个列的表,而输入数据中包含两个连续的分隔符。此时,stringtokenizer的分解结果是5个标记(两个连续的分隔符代表""标记,它将被stringtokenizer忽略),而我们却有6个字段需要设置。同时,我们也不知道连续分隔符在哪里出现,所以也就不知道哪一个列应该设置成""。

当标记本身等同于分隔符(无论是长度还是值)且位于子串之内时,第三个构造函数无效。例如,如果我们要以,为分隔符分解字符串book, author, publication,\",\",date published(这个字符串包含一个,标记,它与分隔符一样),结果是book、author、publication、"、"、date published这六个标记,而不是book、author、publication、,(逗号字符)、date published这五个标记。再提醒一下,即使我们把stringtokenizer的breturntokens参数设置设置成了true,在这种情况下也没有什么帮助。

三、高级字符串分解器

在编写代码之前,你必须搞清楚一个好的分解器有哪些基本要求。因为java开发者已经习惯于使用stringtokenizer类,所以一个好的分解器应该提供stringtokenizer类提供的所有实用方法,比如hasmoretokens()、nexttoken()、counttokens()。

本文提供的代码很简单,而且大部分代码足以自我解释。在这里,我主要利用了stringtokenizer类(创建类实例时breturntokens参数设置为true),并提供了上面提到的几个方法。大多数时候标记与分隔符不同,有些时候分隔符却要作为标记输出(尽管非常罕见),此时如果出现了对标记的请求,分解器要把分隔符作为标记输出。创建powerfultokenizer对象时,你只需要提供输入字符串和分隔符这两个参数,powerfultokenizer将在内部使用breturntokens设置成true的stringtokenizer。(这么做的原因在于,如果不是用breturntokens设置成true的方式创建stringtokenizer,那么它将在解决先前提出的问题时受到限制)。为了正确地控制分解器,代码在几个地方(计算标记的总数量以及nexttoken())检查breturntokens是否设置成了true。

你可能已经发现,powerfultokenizer实现了enumeration接口,从而也就实现了hasmoreelements()和nextelement()这两个方法,而这两个方法又分别把调用直接委托给hasmoretokens()和nexttoken()。(由于实现了enumeration接口,powerfultokenizer实现了与stringtokenizer的向后兼容。)

我们来看一个例子,假设输入字符串是hello, today,,, \"i, am \", going to,,, \"buy, a, book\",分隔符是,。用分解器分割这个字符串时返回结果如表1所示:

表1:字符串分解结果

输入字符串包含11个逗号(,)字符,其中3个在子串里面、4个连续出现(today,,,中包含两个连续逗号,第一个逗号是today的分隔符)。下面是powerfultokenizer计算标记总数的算法:


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons