# bz2-Datei parsen



## littlescrat (23. Apr 2007)

Hi Leute,

meine Studienkollegin und ich haben hier ein "kleines" Problem.

Erst mal zu uns: Wir sind zwei Studenten aus Zweibrücken und haben
eine schwieriges Projekt aufgebrummt bekommen, da wo wir nicht mal
richtig Java programmieren können.
Um so dringender dieser Hilferuf   

Es ist so, dass wir ein 28,5 GB großes XML-File im bz2-Format haben (gepackt)
und mit einem SAX-Parser lesen wollen.

Geht das überhaupt?
Kann Java ein bz2-Format lesen? und das in der Größenordnung?  :bahnhof: 
 :shock: 

Bisher haben wir es nur geschafft, ein reines XML-File einzulesen.
Wollen wir das gesamte entpackte XML-File auslesen, haben
wir es mit rund 512 GB zu tun  :autsch:  :autsch:  :autsch:  :autsch: 
Darum kam der Rat vom Professor selbst: 
Lieber das gepackte bz2-Format auslesen.

Aber geht das denn überhaupt?
Ich hoffe, ihr könnt uns helfen   

Lieben Gruß,

Littlescrat &
Team "Projekt VisuWi"


----------



## Wildcard (23. Apr 2007)

512GB XML? Wer hat denn das verbrochen?  :shock: 
Mir ist dafür keine Lib bekannt und wenn google nichts ausspuckt sieht's schlecht aus.


----------



## Hilefoks (23. Apr 2007)

Interessante Aufgabe und auf jeden Fall lösbar... allerdings nicht gerade eine leichte Aufgabe. ;-)



			
				Wildcard hat gesagt.:
			
		

> Mir ist dafür keine Lib bekannt und wenn google nichts ausspuckt sieht's schlecht aus.


Na, na - nur weil google eine solche Lib nicht ausspuckt ist doch nicht gleich das Kind in den Brunnen gefallen. ;-)

Ihr braucht zunächst einmal eine bz2-Bibliothek die euch die Daten linear blockweise entpacken kann. Mir ist keine solche Bibliothek bekannt, allerdings habe ich eine solche auch noch nie gesucht/gebraucht. Da das bz2-Format aber ein offenes Format ist für das es auch einige Java-Implementierungen gibt, gibt es zumindest einen guten Startpunkt zur eigenen Implementierung (z.B. die von Ant). Ich hoffe ihr versteht in welche Richtung es geht....

MfG,
Hilefoks


----------



## Guest (24. Apr 2007)

Hi  :wink: 

Vielen Dank bisher für eure Ratschläge.
Haben uns angesehen, wie ein GZIPInputStream aufgebaut ist.
Allerdings fragen wir uns, wie wir diesen in unseren SAXParser einbauen könnten.

Und dieser liest in der Tat bz2-Formate?   

Ich gebe mal den Quellcode, der uns bisher das gesamte File eingelesen hat und was ausgab:
(obwohl wir nur Attribute wie Contributor, Title, Timestamp usw. aus dem XML brauchen)


```
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

public class Parser extends DefaultHandler {
	public static void main(String args[]) {
		if (args.length != 1) {
			//System.out.println(args.length);
			System.err.println("Usage: beispiel.xml");
			// System.exit(1);
		}

		// an instance of ourselves as the SAX event handler
		DefaultHandler handler = new Parser();
		// default (non-validating) parser
		SAXParserFactory factory = SAXParserFactory.newInstance();
		try {
			// Set up output stream
			out = new OutputStreamWriter(System.out, "UTF8");

			// Parse the input
			SAXParser saxParser = factory.newSAXParser();
			saxParser.parse(new File("beispiel.xml"),
					handler);

		} catch (Throwable t) {
			t.printStackTrace();
		}
		// System.exit(0);
	}

	static private Writer out;
	
	// ===========================================================
	// SAX DocumentHandler methods
	// ===========================================================

	public void startDocument() throws SAXException {
		nl();
		nl();
		emit("START DOCUMENT");
		nl();
		emit("<?xml version='1.0' encoding='UTF-8'?>");
	}

	public void endDocument() throws SAXException {
		nl();
		emit("END DOCUMENT");
		try {
			nl();
			out.flush();
		} catch (IOException e) {
			throw new SAXException("I/O error", e);
		}
	}

	public void startElement(String namespaceURI, String lName, // local name
			String qName, // qualified name
			Attributes attrs) throws SAXException {
		nl();
		emit("ELEMENT: ");
		String eName = lName; // element name
		if ("".equals(eName))
			eName = qName; // namespaceAware = false
		emit("<" + eName);
		if (attrs != null) {
			for (int i = 0; i < attrs.getLength(); i++) {
				String aName = attrs.getLocalName(i); // Attr name
				if ("".equals(aName))
					aName = attrs.getQName(i);
				nl();
				emit("   ATTR: ");
				emit(aName);
				emit("\t\"");
				emit(attrs.getValue(i));
				emit("\"");
			}
		}
		if (attrs.getLength() > 0)
			nl();
		emit(">");
	}

	public void endElement(String namespaceURI, String sName, // simple name
			String qName // qualified name
	) throws SAXException {
		nl();
		emit("END_ELM: ");
		emit("</" + sName + ">");
	}

	public void characters(char buf[], int offset, int len) throws SAXException {
		nl();
		emit("CHARS: |");
		String s = new String(buf, offset, len);
		emit(s);
		emit("|");
	}

	// ===========================================================
	// Utility Methods ...
	// ===========================================================

	// Wrap I/O exceptions in SAX exceptions, to
	// suit handler signature requirements
	private void emit(String s) throws SAXException {
		try {
			out.write(s);
			out.flush();
		} catch (IOException e) {
			throw new SAXException("I/O error", e);
		}
	}

	// Start a new line
	private void nl() throws SAXException {
		String lineEnd = System.getProperty("line.separator");
		try {
			out.write(lineEnd);
		} catch (IOException e) {
			throw new SAXException("I/O error", e);
		}
	}
}
```

Könnt ihr damit was anfangen?  

Liebe Grüße,

LittleScrat &
Team "Projekt VisuWi"


----------



## littlescrat (24. Apr 2007)

Ops... wir sind leider neu hier.
Hatten vergessen uns einzuloggen  :roll: 

Nicht wundern... dieser "Gast" da oben sind wir -> littlescrat


----------



## Ullenboom (25. Apr 2007)

Das sollte kein Problem sein. Zunächst liefert org.apache.commons.compress.compressors.bzip2.BZip2InputStream aus dem Apache Commons Compress (http://jakarta.apache.org/commons/sandbox/compress/) einen InputStream. Diesen übergibt man dann SAX, oder besser noch StAX:

InputStream   fis = new FileInputStream( file );
InputStream bz2is = new BZip2InputStream( fis );

XMLInputFactory factory = XMLInputFactory.newInstance(); 
XMLStreamReader parser = factory.createXMLStreamReader( bz2is );

Dann geht's an die Elemente. Mehr zu StAX unter http://www.tutego.com/javabuch/javainsel6/javainsel_13_004.htm#Xxx999685.


----------



## littlescrat (25. Apr 2007)

Hi  :wink: 

Das ist ja prima!
Wir werden uns diesen Code anschauen und zusehen, dass das Ding läuft.
Allerdings werden wir das dann erst mit kleineren bz2-Dateien ausprobieren  :### 

Herzlichen Dank noch mal an alle.
Werde dann den Fortschritt bzw. den neuen Code posten, wenn wir alles soweit haben
oder wieder ein Problem auftaucht.   

Eine kleine Frage bleibt im Moment noch:
Wo muss man im Parser eintragen, dass nur die Attribute ausgelesen werden, die man braucht?
Zum Beispiel <contributor> oder <title> usw?

Hier wäre ein kleiner Ausschnit aus dem XML-File:


```
<title>Thema XML</title> 
  <id>1</id> 
- <revision>
  <id>1</id> 
  <timestamp>2007-03-30T11:37:26Z</timestamp> 
- <contributor>
  <ip>bln2-t3-2.xxxxxx.net</ip> 
  </contributor>
```

Lieben Gruß,

LittleScrat &
Team "Projekt VisuWi"


----------



## littlescrat (30. Apr 2007)

Hallo alle zusammen,  :wink: 

wir haben nun wild an dem "StAX-Parser" rumprobiert.
Leider gibt es da ein Problem.
Hier der Quellcode dazu:




```
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.compress.bzip2.CBZip2InputStream;

public class StaxParser {

	public static void main(String[] args) throws Exception {
		InputStream fis = new FileInputStream("beispiel.xml.bz2");
		InputStream bz2is = new BZip2InputStream(fis);
		XMLInputFactory factory = XMLInputFactory.newInstance(); 
		XMLStreamReader xmlStreamReader = factory.createXMLStreamReader( bz2is ); 
		
		/*XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance()
				.createXMLStreamReader(
						new FileInputStream(
								"beispiel.xml"));
								*/
		while (xmlStreamReader.hasNext()) {
			switch (xmlStreamReader.next()) {
			case XMLStreamConstants.START_ELEMENT:
				handleStartElement(xmlStreamReader);
				break;
			case XMLStreamConstants.END_ELEMENT:
				handleEndElement(xmlStreamReader);
				break;
			case XMLStreamConstants.CHARACTERS:
				handleCharacters(xmlStreamReader);
				break;
			default:
			}
		}
		xmlStreamReader.close();
	}

	private static void handleCharacters(XMLStreamReader xmlStreamReader) {
		System.out.print(xmlStreamReader.getText().trim());
	}

	private static void handleEndElement(XMLStreamReader xmlStreamReader) {
		System.out.print("</" + xmlStreamReader.getName() + ">");
	}

	private static void handleStartElement(XMLStreamReader xmlStreamReader) {
		System.out.print("<" + xmlStreamReader.getName());
		int cnt = xmlStreamReader.getAttributeCount();
		for (int i = 0; i < cnt; i++) {
			System.out.print(xmlStreamReader.getAttributeName(i) + "=\""
					+ xmlStreamReader.getAttributeValue(i) + "\"");
			if (i + 1 < cnt) {
				System.out.print(" ");
			}
		}
		System.out.print(">");
	}
}
```

Bei dieser Zeile:

```
import org.apache.commons.compress.bzip2.CBZip2InputStream;
```
Muss der Rechner dazu online sein? Dieser Import funktioniert nicht.
Muss man da noch ein jar-File runterladen?

```
InputStream bz2is = new BZip2InputStream(fis);
```
Deswegen haben wir hier auch einen Fehler. Das Programm erkennt den CBZip2Inputstream nicht   

Könnt ihr uns bitte helfen?

Liebe Grüße,

Littlescrat & 
Team "Projekt VisuWi"


----------



## kleiner_held (2. Mai 2007)

org.apache.commons.compress.bzip2.CBZip2InputStream scheint ein Teil von Jakarta Commons Compress  zu sein. Habt ihr dieses  Paket gedownloaded und ins Projekt eingebunden?


----------



## littlescrat (3. Mai 2007)

Hi  :wink: 

wir wussten nicht, dass wir ein Package runterladen mussten.
Jetzt wissen wir Bescheid. Herzlichen Dank.
Werden den Parser noch mal so neu testen, wenn wir das Package runtergeladen haben  :### 

Liebe Grüße,

Littlescrat & 
Team "Projekt VisuWi"


----------

