当你必须自己实现一个解析器时,你对它的期望会有很多,包括性能良好、灵活、特性丰富、方便使用,以及便于维护等等。说到底,这也是你自己的代码。在本文中,我将为你介绍在Java中实现高性能解析器的一种方式,这种方法并且独一无二,但难度适中,不仅实现了高性能,而且它的模块化设计方式也比较合理。这种设计是受到了VTD-XML的设计方式的启发,后者是我所见过的最快的Java XML解析器,比起StAX和SAX这两种标准的Java XML解析器都要快上许多。

两种基本的解析器类型

为解析器进行分类的方式有好几种,在这里我将解析器分为两种基础类型:

顺序访问解析器

随机访问解析器

顺序访问是指解析器对进行数据进行解析,在数据解析完成后将其转交给数据处理器(processor)的过程。数据处理器只能访问当前正在进行解析的数据,它既不能访问已解析过的数据,也不能访问等待解析的数据。这种解析器也被称为基于事件的解析器,例如SAX和StAX解析器。

而随机访问解析器是指解析器允许数据处理代码可以随意访问正在进行解析的数据之前和之后的任意数据(随机访问)。这种解析器的例子有XML DOM解析器。

下图展示了顺序访问解析器与随机访问解析器的不同之处:

顺序访问解析器只能让你访问当前正在解析的“视窗”或“事件”,而随机访问解析器允许你任意地浏览所有已解析数据。

设计概况

我在这里所介绍的解析器设计属于随机访问解析器。

随机访问解析器的实现通常会慢于顺序访问解析器,因为它们一般都会为已解析数据创建某种对象树,数据处理代码将通过这棵树对数据进行访问。创建这种对象树不仅要花费较长的CPU时间,消耗的内存也很大。

相对于从已解析数据中创建一棵对象树的方式,另一种性能更佳的方式是为原来的数据缓冲区建立一个对应的索引缓冲区,这些索引会指向在已解析数据中找到的元素的起点与终点。数据处理代码此时不再通过对象树访问数据,而是直接在包括了原始数据的缓冲区中访问已解析数据。以下是对这两种处理方式的图示:

由于我找不到一个更好的名字,因此我将这种方式简单地命名为“索引覆盖解析器”(Index Overlay Parser)。该解析器为原始数据创建了一个覆盖于其上的索引。这种方式让人联想起数据库索引将数据保存在磁盘的方式,它为原始的、未处理的数据创建了一个索引,以实现更快地浏览和搜索数据的目的。

如同我之前所说的,这种设计方式是受到了VTD-XML(VTD是指虚拟令牌描述符)的启发,因此你也可以把这种解析器称为虚拟令牌描述符解析器。但我还是倾向于索引覆盖这个名字,因为它表现了虚拟令牌描述符的本质,即对原始数据建立的索引。

解析器设计概要

一种常规的解析器设计方式将解析过程分为两步。第一步是将数据分解为内聚的令牌,一个令牌是已解析数据中的一个或多个字节或字符。第二步是对令牌进行解释,并根据这些令牌构建更大的元素。以下是这两个步骤的图示:

这里的元素并不一定是指XML元素(虽然XML元素也是解析器元素),而是指构成解析数据的更大的“数据元素”。比如说,在一个XML文档中元素代表了XML元素,而在一个JSON文档中元素则代表了JSON对象,等等。

举例来说,这个字符串可以被分解为以下几个令牌:

<

myelement

>

一旦数据被分解为令牌,解析器就能够相对容易地了解它的意义,并且决定这些令牌构成的更大的元素。解析器就能够理解一个XML元素是由一个’’令牌结尾。

索引覆盖解析器设计

在这种解析器的设计方式中也包含了两个步骤:输入数据首先被一个令牌生成器(tokenizer)组件分解为令牌,解析器随后将对令牌进行解析,以决定输入数据的一个更大的元素边界。

你也可以为解析过程加入一个可选的“元素浏览步骤”。如果解析器从解析数据中构建出一棵对象树,它通常会包含在整棵树中进行浏览的链接。如果我们不选择对象树,而是构建出一个元素索引缓冲区,我们也许需要另一个组件以帮助数据处理代码在元素索引缓冲区中进行浏览。

以下是我们的解析器设计的概要:

我们首先将所有数据读入一个数据缓冲区中,为了能够通过在解析过程中创建的索引对原始数据进行随机访问,所有的原始数据必须已经存在于内存中。

第二步,令牌生成器会将数据分解为令牌。令牌生成器内部的某个令牌缓冲区会将该令牌的起点索引、终点索引和令牌类型都保留下来。使用令牌缓冲区使你能够查找之前或之后的令牌,在这种设计中解析器会利用到这一项特性。

第三步,解析器获取了令牌生成器所产生的令牌,根据上下文对其进行验证,并决定它所表示的元素。随后解析器会根据从令牌生成器处获取的令牌构建一个元素索引(即索引覆盖)。解析器会从令牌生成器中一个接一个地获取令牌。因此令牌生成器不必立即将所有数据都分解为令牌,它只需要每次找到一个令牌就行了。

数据处理代码将浏览整个元素缓冲区,利用它访问原始数据。你也可以选择用一个元素浏览组件将元素缓冲区包装起来,使浏览元素缓冲区的工作更加简单。

这种设计不会从解析数据中生成一棵对象树,但它确实生成了一个可浏览的结构,即元素缓冲区,索引(即整数数组)将指向包含了原始数据的数据缓冲区。你可以使用这些索引浏览原始数据缓冲区中的所有数据。

【Java开发学习交流群02】 群号215703787

解析器 java_Java高性能解析器实现思路及方法学习相关推荐

  1. dvd管理器java_Java DVD管理器 基础示例代码下载

    [实例简介] [实例截图] [核心代码] import java.text.ParseException; import java.text.SimpleDateFormat; import java ...

  2. 抢答器java_java竞争抢答器

    /*实现一个竞拍抢答程序:要求设置三个抢答者(三个线程),而后同时发出抢答指令,抢答成功者显示成功提示,抢答失败者给出失败提示.*/ package Java多线程_01; import java.u ...

  3. Java高性能解析器实现思路及方法

    在某些情况下,你可能需要在Java中实现你自己的数据或语言解析器,也许是这种数据格式或语言缺乏标准的Java或开源解析器可以使用.或者虽然有现成的解析器实现,但它们要么太慢,要么太占内存,要么就是没有 ...

  4. java 解析器_高性能Java解析器实现过程详解

    如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器.或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能.或者开源解析 ...

  5. WPF ---- ​xmal 解析器没有办法解析类的TypeConverter

    xmal 解析器没有办法解析类的TypeConverter.代码如下 页面代码: <Window x:Class="WpfApplication_xmln.Windows.Conver ...

  6. python的网页解析器_Python网页解析器使用实例详解

    python 网页解析器 1.常见的python网页解析工具有:re正则匹配.python自带的html.parser模块.第三方库BeautifulSoup(重点学习)以及lxm库. 2.常见网页解 ...

  7. php云解析播放器,xyplay云解析PHPV3.4.1优化稳定版视频解析

    演示地址:如有演示站请以演示为准,无演示站以截图为准,源码太多服务器有限,无法搭建所有源码演示站,请谅解! 新手购买指导:1.在本站注册账号 丨 2.登录已注册账号充值源码所需金币 丨 3.登录账号下 ...

  8. scrapy使用代理报错keyerror: proxy_爬虫Scrapy框架-Crawlspider链接提取器与规则解析器...

    Crawlspider 一:Crawlspider简介 CrawlSpider其实是Spider的一个子类,除了继承到Spider的特性和功能外,还派生除了其自己独有的更加强大的特性和功能.其中最显著 ...

  9. 类加载机制、双亲委派机制深度解析以及如何自定义类加载器

    文章目录 1.类加载运行的全过程 2. JVM类加载器的初始化 3.双亲委派机制 4.编写自定义类加载器 5.(Tomcat)如何打破双亲委派机制 当我们运行一个类的时候,首先要通过类加载机制把类加载 ...

最新文章

  1. CSM+3PAR帮助XXX教育技术中心
  2. 图解数据中心水系统标准和架构(大全)
  3. 长庆企业信息化管理课件_详解:企业信息化管理系统,不能马虎对待
  4. 关于cookie 跨页面处理
  5. python数据标准类型_Python的标准数据类型(下)
  6. oracle 11g RAC无法采用deinstall自动卸载grid,手动卸载,超级棒!
  7. 软件测试—软件测试基础知识—测试用例设计的方法之场景法、正交试验法和错误推断法
  8. 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析
  9. Python实现七段数码管时钟(动态刷新版)
  10. ol2 和 bootstrap样式冲突的问题
  11. 程序员如何面对自己三十岁后的下坡路?
  12. highcharts 使用实例
  13. 在 Go 语言中使用 Log 包--转自GCTT
  14. 2021 年电工杯 B 题
  15. Windows系统安装adb/fastboot驱动教程
  16. android 指南针图片,如何在android中制作自定义指南针视图
  17. 网页服务器怎么做链接,如何做网页超级链接
  18. OpenOCD failed tor read memory at $addr 错误
  19. 项目提示JDK版本问题或者语言级别问题时的解决办法
  20. eden区分配至s0、s1

热门文章

  1. 基于JAVA+SpringMVC+Mybatis+MYSQL的新闻头条管理系统
  2. set identity_insert on 不起作用
  3. 心理软件测试自学,软件测试中的心理学
  4. oracle重启 日志_超详细的数据库主机及数据库日志收集总结
  5. php钩子是啥意思,thinkphp钩子是什么意思
  6. Cisco无线mDNS
  7. WPF中DatePiker值绑定以及精简查询
  8. jenkins与SonarQube集成
  9. codeforces 85D. Sum of Medians
  10. 中文女和程序员的爱情奇遇[转]