java - una - Usando el analizador SAX en un archivo xml dentro de un zip
comprimir varios archivos en un zip con java (2)
Puede analizar un XML utilizando un InputStream como fuente. Entonces puede abrir un ZipFile , obtener el InputStream de la entrada que desea y luego analizarlo. Vea el método getInputStream .
---- Editar ----
Aquí hay un código para guiarte:
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();
}
}
Esto puede estar más allá de las capacidades de Java VM debido al tamaño de los archivos tratados (archivos xml de 50-100MB)
En este momento tengo un conjunto de archivos xml enviados como cremalleras, que a su vez se descomprimen todos y luego todo el XML en el directorio se procesa uno a la vez usando SAX.
Para ahorrar tiempo y espacio (ya que la compresión es de aproximadamente 1:10) me preguntaba si hay una forma de pasar un ZipFileEntry que es un archivo xml a un manejador de SAX.
Lo he visto usando DocumentBuilder y otros métodos de análisis xml, pero para el rendimiento (y especialmente para la memoria) me estoy quedando con SAX.
Actualmente estoy usando SAX de la siguiente manera
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 );
}
-
ZipInputStream.read()
leería x número de bytes deZipFileEntry
, los descomprimiría y le daría los bytes descomprimidos. - Use cualquiera de los métodos aquí para crear una secuencia de entrada / salida.
- Dele esa secuencia de entrada / salida como
InputStream
a su analizador. - Comience a escribir datos descomprimidos en la secuencia de entrada / salida (ahora tratada como
OutputStream
). - Así que ahora está leyendo fragmentos de datos del archivo zip, descomprimiéndolos y pasándolos al analizador.
PD:
- Si el archivo zip contiene varios archivos, vea esto: extraer contenidos de las entradas de ZipFile cuando se lee desde byte [] (Java) , tendrá que marcar un punto para saber cuándo llega al final de una entrada.
- No uso mucho el analizador de SAX, pero supongo que analizará el archivo de esta manera (cuando se da en fragmentos).
--- editar ---
Esto es lo que quise decir:
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();
}
}
}