Java 在zip中的xml文件上使用SAX解析器
由于要处理的文件(50-100MB xml文件)的大小,这可能超出Java VM的能力 现在我有一组xml文件作为ZIP发送,这些文件依次被解压缩,然后目录中的所有xml都使用SAX一次处理一个 为了节省时间和空间(因为压缩大约是1:10),我想知道是否有一种方法可以将作为xml文件的ZipFileEntry传递给SAX处理程序 我见过它是使用DocumentBuilder和其他xml解析方法完成的,但对于性能(尤其是内存),我坚持使用SAX 目前,我以以下方式使用SAXJava 在zip中的xml文件上使用SAX解析器,java,xml-parsing,zip,saxparser,Java,Xml Parsing,Zip,Saxparser,由于要处理的文件(50-100MB xml文件)的大小,这可能超出Java VM的能力 现在我有一组xml文件作为ZIP发送,这些文件依次被解压缩,然后目录中的所有xml都使用SAX一次处理一个 为了节省时间和空间(因为压缩大约是1:10),我想知道是否有一种方法可以将作为xml文件的ZipFileEntry传递给SAX处理程序 我见过它是使用DocumentBuilder和其他xml解析方法完成的,但对于性能(尤其是内存),我坚持使用SAX 目前,我以以下方式使用SAX SAX
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
MyHandler handler = new MyHandler();
for( String curFile : xmlFiles )
{
System.out.println( "\n\n\t>>>>> open " + curFile + " <<<<<\n");
saxParser.parse( "file://" + new File( dirToProcess + curFile ).getAbsolutePath(), handler );
}
SAXParserFactory=SAXParserFactory.newInstance();
SAXParser SAXParser=factory.newSAXParser();
MyHandler=新的MyHandler();
for(字符串curFile:xmlFiles)
{
System.out.println(“\n\n\t>>>open”+curFile+”您可以使用InputStream作为源。因此,您可以打开,获取所需条目的InputStream,然后对其进行解析。请参阅方法
----编辑----
以下是一些代码来指导您:
for( String curFile : xmlFiles )
{
ZipFile zip = new ZipFile(new File( dirToProcess + curFile));
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()){
ZipEntry entry = entries.nextElement();
InputStream xmlStream = zip.getInputStream(entry);
saxParser.parse( xmlStream, handler );
xmlStream.close();
}
}
for(字符串curFile:xmlFiles)
{
ZipFile zip=new ZipFile(新文件(dirToProcess+curFile));
枚举
- 将从
ZipFileEntry
中读取x个字节,将它们解压缩并提供解压缩后的字节
- 使用任何方法创建输入/输出流
- 将该输入/输出流作为
InputStream
提供给解析器
- 开始将解压后的数据写入输入/输出流(现在被视为
OutputStream
)
- 现在,您正在从zip文件中读取数据块,解压缩它们并将它们传递给解析器
附言:
如果zip文件包含多个文件,请参见:,您必须进行检查,以便在到达条目末尾时知道
我不太了解SAX解析器,但假设它将以这种方式解析文件(当以块形式给出时)
---编辑---
我的意思是:
import java.io.File;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class Main {
static class MyRunnable implements Runnable {
private InputStream xmlStream;
private SAXParser sParser;
public MyRunnable(SAXParser p, InputStream is) {
sParser = p;
xmlStream = is;
}
public void run() {
try {
sParser.parse(xmlStream, new DefaultHandler() {
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
System.out.println("\nStart Element :" + qName);
}
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("\nEnd Element :" + qName);
}
});
System.out.println("Done parsing..");
} catch (Exception e) {
e.printStackTrace();
}
}
}
final static int BUF_SIZE = 5;
public static void main(String argv[]) {
try {
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
ZipFile zip = new ZipFile(new File("D:\\Workspaces\\Indigo\\Test\\performance.zip"));
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
// in stream for parser..
PipedInputStream xmlStream = new PipedInputStream();
// out stream attached to in stream above.. we would read from zip file and write to this..
// thus passing whatever we write to the parser..
PipedOutputStream out = new PipedOutputStream(xmlStream);
// Parser blocks in in stream, so put him on a different thread..
Thread parserThread = new Thread(new Main.MyRunnable(saxParser, xmlStream));
parserThread.start();
ZipEntry entry = entries.nextElement();
System.out.println("\nOpening zip entry: " + entry.getName());
InputStream unzippedStream = zip.getInputStream(entry);
byte buf[] = new byte[BUF_SIZE]; int bytesRead = 0;
while ((bytesRead = unzippedStream.read(buf)) > 0) {
// write to err for different color in eclipse..
System.err.write(buf, 0, bytesRead);
out.write(buf, 0, bytesRead);
Thread.sleep(150); // theatrics...
}
out.flush();
// give parser a couple o seconds to catch up just in case there is some IO lag...
parserThread.join(2000);
unzippedStream.close(); out.close(); xmlStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
导入java.io.File;
导入java.io.InputStream;
导入java.io.PipedInputStream;
导入java.io.PipedOutputStream;
导入java.util.Enumeration;
导入java.util.zip.ZipEntry;
导入java.util.zip.ZipFile;
导入javax.xml.parsers.SAXParser;
导入javax.xml.parsers.SAXParserFactory;
导入org.xml.sax.Attributes;
导入org.xml.sax.SAXException;
导入org.xml.sax.helpers.DefaultHandler;
公共班机{
静态类MyRunnable实现Runnable{
私有输入流xmlStream;
私家车;
公共MyRunnable(SAXP解析器,InputStream为){
稀疏=p;
xmlStream=is;
}
公开募捐{
试一试{
parse(xmlStream,新的DefaultHandler(){
public void startElement(字符串uri、字符串localName、字符串qName、属性)
抛出SAX异常{
System.out.println(“\n起始元素:“+qName”);
}
public void endElement(字符串uri、字符串localName、字符串qName)引发SAXException{
System.out.println(“\n元素:+qName”);
}
});
System.out.println(“完成解析…”);
}捕获(例外e){
e、 printStackTrace();
}
}
}
最终静态int BUF_尺寸=5;
公共静态void main(字符串argv[]){
试一试{
SAXParser SAXParser=SAXParserFactory.newInstance().newSAXParser();
ZipFile zip=新ZipFile(新文件(“D:\\workspace\\Indigo\\Test\\performance.zip”);
枚举(0){
//在eclipse中写入不同颜色的错误。。
系统错误写入(buf,0,字节读取);
out.write(buf,0,字节读取);
Thread.sleep(150);//戏剧。。。
}
out.flush();
//给解析器几秒钟的时间,以防IO延迟。。。
parserThread.join(2000);
解压缩流.close();out.close();xmlStream.close();
}
}捕获(例外e){
e、 printStackTrace();
}
}
}
请参阅我在上面添加的示例当前实现,不确定如何将流与sax解析调用一起使用非常大的文件(尽管需要30分钟才能运行)。请参阅我在上面添加的示例当前实现,不确定如何将流与sax解析调用一起使用