Java 在zip中的xml文件上使用SAX解析器

Java 在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

由于要处理的文件(50-100MB xml文件)的大小,这可能超出Java VM的能力

现在我有一组xml文件作为ZIP发送,这些文件依次被解压缩,然后目录中的所有xml都使用SAX一次处理一个

为了节省时间和空间(因为压缩大约是1:10),我想知道是否有一种方法可以将作为xml文件的ZipFileEntry传递给SAX处理程序

我见过它是使用DocumentBuilder和其他xml解析方法完成的,但对于性能(尤其是内存),我坚持使用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解析调用一起使用