在项目里面遇到了一些被解析的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解析...
1. **解析和编译XSD文档**:它可以解析XML Schema文件,并将其编译成内部表示,以便进行快速的验证和查询。 2. **验证XML文档**:通过编译的XSD模型,可以验证XML文档是否符合定义的模式,确保数据的有效性。 3. *...
TinyXML-2(通常简称为tinyxml2)是一个轻量级的C++库,专门设计用来解析和操作XML文档。这个库小巧、简单且易于集成到项目中,尤其适合对性能要求不高的应用。 本项目“tinyxml2解析XML文件读取数据”主要关注如何...
本文将深入探讨如何使用C++来解析XML文件,主要围绕“C++实现对xml文件的解析”这一主题展开。 XML文件通常包含一系列元素,每个元素都有开始标签、结束标签和可能的属性。C++中解析XML文件的方法多种多样,这里...
本文将深入探讨使用C++实现XML文档解析的相关知识点,包括XML的基本结构、解析器的工作原理以及如何利用C++进行XML的读取、查询、删除、添加和保存操作。 XML文档的基础结构: XML文档由一系列元素组成,每个元素都...
1、可以批量同时处理多个XML文件,适合需要批量修改XML文件中部分内容的需求 2、可以支持文本替换,就是说,只要匹配其中的内容,就可以实现一键将原本的文本内容或者节点的内容,替换成需要替换的内容 可扩展的功能...
在“Xml之DOM解析--学生成绩管理系统”中,我们主要探讨如何使用DOM解析器来读取、处理和更新XML文件,以实现一个简单的学生成绩管理系统的功能。首先,我们需要理解DOM解析的基本流程: 1. **加载XML文档**:使用...
1. **配置伺服驱动器**:通过读取和写入XML文件,用户可以批量设置多个伺服驱动器的参数,简化了设备的初始化工作。 2. **运动控制**:XML文件可以包含预定义的运动轨迹或动作序列,使得驱动器按照预定的路径执行...
C# 生成 XML 文件,编码为 UTF-8 方法 C# 生成 XML 文件,编码为 UTF-8 方法是指在 C# 编程语言中,使用特定的方法和类来生成 XML 文件,并将其编码为 UTF-8 编码格式的过程。这种方法常用于数据交换、配置文件、...
本文将深入探讨使用C语言编写的XML文件解析源码,并讲解如何实现XML文件的基本操作,如查找、增加和删除节点。 在C语言中处理XML文件通常涉及到以下几个关键步骤: 1. **内存管理**:由于C语言没有内置的高级数据...
本项目名为“天气预报 .xml文件解析”,其核心在于利用XML文件来存储天气预报数据,并通过编程手段进行解析,结合SQLite数据库展示和管理这些信息。 首先,我们要理解XML的基本结构。XML是一种自描述性的标记语言,...
通过minixml,嵌入式系统开发者能够在受限的环境下实现XML数据的解析和处理,极大地扩展了嵌入式系统的数据处理能力。使用minixml,不仅可以读取配置文件,还可以与服务器进行XML数据交换,或者解析XML格式的协议...
xmlschema-core-2.0.1.jar
为了解决这个问题,我们可以采用分段(SAX或StAX)的方式进行XML解析,这种方法可以高效地处理大文件,减少内存消耗。 1. **分段解析(SAX解析)**: SAX(Simple API for XML)是一种事件驱动的解析器,它不会一...
根据给定文件中的标题、描述、标签以及部分内容,可以总结并深入探讨以下关于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协议的数据...
在本文中,我们将深入探讨如何使用C#编程语言解析XML文件,并将其内容在Windows Forms(WinForm)应用程序中展示。XML(eXtensible Markup Language)是一种数据存储和交换的标准格式,而C#是Microsoft .NET框架下...