在项目里面遇到了一些被解析的xml文件超过30M 或 60M 以上的情况, 现在已经不好去说为什么不在一开始产生xml的情况下就把xml 做小点,但是遇到这个问题后,我只能解决问题了,解决问题同时害怕重复发明轮子,我也去看了下现有的xml 解析东西,jdom 的SAXBuilder和 dom4j 的SAXReader都是把XML文件一次读入,xml文件过来 会报溢出的异常 但即使SAXParser是可以批量读入解析,但它也是一次解析完,假设XML文件中有一万条数据,解析后就必须在内存中放这么多的对象 个人觉得这样有些不灵活,就自己做了个小东西来切分 但前提是这个xml文件得有文件头 <?xml version="1.0" encoding="GBK"?> encoding必须跟文件编码格式一致 ,不然解析的时候会出乱码。
个人水平有限,但很希望得到大家的指正,希望大家不吝啬手中的砖头
package searchRing.ring.util.xmlBufferTool;
import java.io.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class XMLBufferTool {
private static final int defaultLineCount = 10;
private static final int defaultMaxOutputSize = 50;
private static final Pattern elementPattern = Pattern.compile("<[a-zA-Z]+>");
private static final Pattern charSetPattern = Pattern.compile("<[?][[0-9a-zA-Z]|[\\s]|[=]|[\"]|[.]|[-]]+[?]>");
private StringBuffer xmlContentBuffer;
/* just used to store and output the data divided */
XMLOutputBuffer xmlOutput;
private String charSetTitle = "";
private String rootElemetMark = "";
private String childElementMark = "";
InputStreamReader bufferedReader;
InputStream fileInputStream;
public XMLBufferTool(String xmlFilePath) {
this.xmlContentBuffer = new StringBuffer();
try {
this.fileInputStream = new FileInputStream(xmlFilePath);
// bufferedReader = new InputStreamReader(fileInputStream, "UTF-8");
String charSet = getCharSet(xmlFilePath);
if (charSet != null)
bufferedReader = new InputStreamReader(fileInputStream, charSet);
else
bufferedReader = new InputStreamReader(fileInputStream);
} catch (FileNotFoundException fe) {
fe.printStackTrace();
} catch (UnsupportedEncodingException uee) {
uee.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
try {
preparePaser();
} catch (IOException ie) {
ie.printStackTrace();
}
}
public String getCharSetTitle() {
return charSetTitle;
}
public String getRootElemetMark() {
return rootElemetMark;
}
private String getCharSet(String filePath) throws IOException {
char temp[] = new char[512];
FileInputStream tempInput = new FileInputStream(filePath);
InputStreamReader tempReader = new InputStreamReader(tempInput);
int i = tempReader.read(temp);
tempReader.close();
tempInput.close();
if (i < 0)
return null;
String tempStr = new String(temp);
Matcher m = charSetPattern.matcher(tempStr);
if (m.find()) {
String charSetStr = tempStr.substring(m.start(), m.end());
Pattern tempP = Pattern.compile("[\"][[0-9a-zA-Z]|[-]]+[\"]");
Matcher tempM = tempP.matcher(charSetStr);
if (tempM.find()) {
String charSet = charSetStr.substring(tempM.start(), tempM.end());
return charSet.substring(1, charSet.length() - 1);
}
}
return null;
}
private void preparePaser() throws IOException {
readSomeLine(defaultLineCount);
Matcher m = charSetPattern.matcher(xmlContentBuffer);
if (m.find()) {
this.charSetTitle = this.xmlContentBuffer.substring(m.start(), m.end());
this.xmlContentBuffer.delete(0, m.end());
}
m = elementPattern.matcher(xmlContentBuffer);
if (m.find()) {
this.rootElemetMark = this.xmlContentBuffer.substring(m.start(), m.end());
this.xmlContentBuffer.delete(0, m.end());
}
m = elementPattern.matcher(xmlContentBuffer);
if (m.find()) {
this.childElementMark = this.xmlContentBuffer.substring(m.start(), m.end());
}
this.xmlOutput = new XMLOutputBuffer(this.childElementMark);
parserBuffer();
}
private int readSomeLine(int lineCount) throws IOException {
char buffer[] = new char[1024];
int i = 0;
int index = 0;
/* be careful of the sequence of the boolean caculation */
while (i++ < lineCount && (index = this.bufferedReader.read(buffer)) > 0) {
xmlContentBuffer.append(buffer, 0, index);
}
return index;
}
private void parserBuffer() {
int lastIndex = this.xmlContentBuffer.lastIndexOf(this.childElementMark);
if (lastIndex > 0) {
this.xmlOutput.append(this.xmlContentBuffer.substring(0, lastIndex));
this.xmlContentBuffer.delete(0, lastIndex);
}
}
public StringBuffer popDividedDataAfterParser() throws IOException {
while (this.xmlOutput.getItemCount() < defaultMaxOutputSize) {
int i = readSomeLine(defaultLineCount);
parserBuffer();
if (i < 0)
break;
}
if (this.xmlOutput.getItemCount() == 0)
return null;
StringBuffer returnSB = this.xmlOutput.getXmlOutput();
this.xmlOutput.clearBuffer();
return returnSB.insert(0, this.rootElemetMark).append(this.rootElemetMark.replaceFirst("<", "</"));
}
public static void main(String args[]) throws Exception {
String str = "F:/ringInfoXML/ringTime.xml";
XMLBufferTool xmlb = new XMLBufferTool(str);
StringBuffer s = xmlb.popDividedDataAfterParser();
int i = 0;
Matcher m = Pattern.compile("<ring>").matcher(s);
while (m.find())
i++;
System.out.println(i);
System.out.println(s);
}
private static class XMLOutputBuffer {
private StringBuffer xmlOutput;
private int itemCount;
private Pattern markPattern;
XMLOutputBuffer(String markStr) {
this.markPattern = Pattern.compile(markStr);
xmlOutput = new StringBuffer();
itemCount = 0;
}
public void append(String str) {
if (str == null || "".equals(str))
return;
this.xmlOutput.append(str);
Matcher m = this.markPattern.matcher(str);
while (m.find())
this.itemCount++;
}
public void clearBuffer() {
xmlOutput = new StringBuffer();
this.itemCount = 0;
}
public StringBuffer getXmlOutput() {
return xmlOutput;
}
public int getItemCount() {
return itemCount;
}
}
}
代码中popDividedDataAfterParser() 输出的StringBuffer 可用来初始化一个 StringReader 再给dom4j 的saxReader去解析,这样联合一起用, 想处理多少,就先分出来解析多少,特别适合多线程的生产者和消费者的那种情况,希望对大家有用
分享到:
相关推荐
标题中的“kettle批量解析多个xml文件”指的是使用Kettle(也称为Pentaho Data Integration,简称PDI)工具处理XML文件的批量操作。Kettle是一款开源的数据集成工具,它提供了丰富的转换和作业来实现数据抽取、转换...
TinyXML-2 是一个简单、小型、高效的 C++ XML 解析器,可以被轻松集成到其他程序中。它使用文档对象模型(DOM)的方式解析XML,可解析 XML 文档,并根据该文档构建可读取、修改和保存的文档对象模型。 作为XML解析...
TinyXML-2(通常简称为tinyxml2)是一个轻量级的C++库,专门设计用来解析和操作XML文档。这个库小巧、简单且易于集成到项目中,尤其适合对性能要求不高的应用。 本项目“tinyxml2解析XML文件读取数据”主要关注如何...
本文将深入探讨使用C++实现XML文档解析的相关知识点,包括XML的基本结构、解析器的工作原理以及如何利用C++进行XML的读取、查询、删除、添加和保存操作。 XML文档的基础结构: XML文档由一系列元素组成,每个元素都...
在“Xml之DOM解析--学生成绩管理系统”中,我们主要探讨如何使用DOM解析器来读取、处理和更新XML文件,以实现一个简单的学生成绩管理系统的功能。首先,我们需要理解DOM解析的基本流程: 1. **加载XML文档**:使用...
- 内存消耗大:对于大型XML文件,DOM可能会消耗大量内存,因为它需要一次性加载整个文档。 - 性能问题:由于需要构建完整的DOM树,解析速度相对较慢。 **2. SAX解析** SAX(Simple API for XML)是一种事件驱动的...
1、可以批量同时处理多个XML文件,适合需要批量修改XML文件中部分内容的需求 2、可以支持文本替换,就是说,只要匹配其中的内容,就可以实现一键将原本的文本内容或者节点的内容,替换成需要替换的内容 可扩展的功能...
C# 生成 XML 文件,编码为 UTF-8 方法 C# 生成 XML 文件,编码为 UTF-8 方法是指在 C# 编程语言中,使用特定的方法和类来生成 XML 文件,并将其编码为 UTF-8 编码格式的过程。这种方法常用于数据交换、配置文件、...
1. **配置伺服驱动器**:通过读取和写入XML文件,用户可以批量设置多个伺服驱动器的参数,简化了设备的初始化工作。 2. **运动控制**:XML文件可以包含预定义的运动轨迹或动作序列,使得驱动器按照预定的路径执行...
本文将深入探讨使用C语言编写的XML文件解析源码,并讲解如何实现XML文件的基本操作,如查找、增加和删除节点。 在C语言中处理XML文件通常涉及到以下几个关键步骤: 1. **内存管理**:由于C语言没有内置的高级数据...
本项目名为“天气预报 .xml文件解析”,其核心在于利用XML文件来存储天气预报数据,并通过编程手段进行解析,结合SQLite数据库展示和管理这些信息。 首先,我们要理解XML的基本结构。XML是一种自描述性的标记语言,...
通过minixml,嵌入式系统开发者能够在受限的环境下实现XML数据的解析和处理,极大地扩展了嵌入式系统的数据处理能力。使用minixml,不仅可以读取配置文件,还可以与服务器进行XML数据交换,或者解析XML格式的协议...
* 本类是专门解析XML文件的,主要用于为系统读取自己的配置文件时提供最方便的解析操作 * @author HX * */ public class XmlManager { /** * 得到某节点下某个属性的值 * @param element 要获取属性的...
根据给定文件中的标题、描述、标签以及部分内容,可以总结并深入探讨以下关于C#中XML解析的关键知识点: ### C#中的XML解析方式 #### 1. XML Text Reader(流式解析) - **简介**:在.NET框架中,`XMLTextReader`...
这种方式适用于小到中型的XML文件,因为它一次性加载整个文件,内存消耗较大。 2. SAX解析:SAX是一种事件驱动的解析器,它逐行读取XML文件,遇到元素、属性等时触发相应的事件回调。这种方式适用于处理大型XML文件...
在C语言环境中,处理XML文档通常需要使用XML解析器,其中Mini-xml是一个小巧且独立的解决方案。 Mini-xml是由D. J. Butler开发的一个开源项目,它的设计目标是提供一个轻量级的XML解析和生成工具,特别适合于资源...
1. **序列化**:将解析后的DOM树或处理过的XML数据重新序列化成XML字符串或文件。 2. **格式化输出**:在导出时可以控制缩进、换行等,使得XML文件更易读。 ### 实际应用 1. **Web服务**:XML常作为SOAP协议的数据...
这种解析方式的优点是可以方便地通过节点关系进行遍历和修改,但缺点是占用内存大,尤其对于大型XML文件,可能导致性能问题。 2. SAX(Simple API for XML) SAX解析器是一种基于事件驱动的解析方式,它不会一次性...
Pull解析器是一种事件驱动的解析方式,它允许应用程序在解析过程中按需获取XML数据,而不是一次性加载整个文档到内存,这使得处理大型XML文件时更为高效。 ### XML解析方式对比 在Android中,XML解析主要有三种...
在IT领域,XML文件解析是处理和读取XML数据的关键步骤。以下是一些关于解析XML文件的知识点: 1. XML结构: - 根元素:XML文档必须有一个根元素,所有其他元素都包含在这个根元素内。 - 元素:XML中的基本单位,...