JZlib

Zertos

Mitglied
Ich hab da ein Problem mit JZLib bzw. generell mit ZLib.
Ich hab hier eine Datei 8000-L049.pck, die mit ZLib komprimiert wurde.
Entweder mache ich irgendetwas falsch oder es funktioniert nicht mit der Java Version von ZLib, um Dateien zu dekomprimieren.
Das eingebaute ZLib in Java (java.util.zip.Inflater) habe ich auch schon erfolglos verwendet.

Die komprimierte Datei (.pck): http://dl.dropbox.com/u/44975779/8000-L049.pck
Die dekomprimierte Datei (.xml): http://dl.dropbox.com/u/44975779/8000-L049.xml

Hier mal meine Testversuche.
Zuerst habe ich es mit dem eingebauten Inflater versucht:
Java:
package zip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

public class ZLib
{
	public static void main(String[] args) throws IOException, DataFormatException
	{
		File file = new File("8000-L049.pck");		
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(file + ".xml");
		Inflater decompressor = new Inflater();
		byte[] data = new byte[(int)file.length()];
		
		fis.read(data);
		fis.close();
		
		decompressor.setInput(data);
		int test = decompressor.inflate(data);		
		System.out.println(test);
		
		for (int i = 0; i < data.length; i++)
		{
			fos.write(data[i]);
		}
		
		fos.close();
	}
}

Als Exception erhalte ich eine DataFormatException:
Java:
Exception in thread "main" java.util.zip.DataFormatException: incorrect header check
	at java.util.zip.Inflater.inflateBytes(Native Method)
	at java.util.zip.Inflater.inflate(Unknown Source)
	at java.util.zip.Inflater.inflate(Unknown Source)
	at zip.ZLib.main(ZLib.java:24)
Und die erstellte .xml Datei hat 0 Bytes.


Dann habe ich mal auf JZLib zurückgegriffen und auch zwei erfolglose Tests versucht.
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import com.jcraft.jzlib.*;

public class Test_PCK
{
	@SuppressWarnings({ "deprecation" })
	public static void main(String[] args) throws IOException
	{
		File file = new File("8000-L049.pck");		
		FileInputStream fis = new FileInputStream(file);
		ZInputStream zis = new ZInputStream(fis, JZlib.Z_PARTIAL_FLUSH);
		FileOutputStream fos = new FileOutputStream(file + ".xml");
		byte[] data = new byte[(int)file.length()];
		byte[] buffer = new byte[1024 * 16];
		
		zis.read(buffer);
		System.out.println(zis.getTotalIn() + " " + zis.getTotalOut());
		
		for (int i = 0; i < data.length; i++)
		{
			fos.write(buffer[i]);
		}
	}
}
Ausgegeben wird 512 2, also sind 512 Bytes im ZInputStream, es werden aber nur 2 Bytes rausgeschrieben. Warum auch immer.
Die erstellte .xml Datei hat auch wieder 0 Bytes.

Der zweite Versuch:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import com.jcraft.jzlib.*;

public class Test_PCK2
{
	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws IOException
	{
		File file = new File("8000-L049.pck");		
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(file + ".xml");
		
		byte[] buffer = new byte[1024 * 5];
		
		fis.read(buffer);
		
		Inflater decompressor = new Inflater();
		System.out.println("Größe Buffer: " + buffer.length + " bytes");
		decompressor.setInput(buffer);
		System.out.println("Input: " + decompressor.getAvailIn() + " bytes");
		int i = decompressor.inflate(JZlib.Z_FULL_FLUSH);
		System.out.println("Output: " + i + " bytes");
		
		fos.write(buffer, 0, buffer.length);
	}
}
Konsole gibt folgendes aus:
Java:
Größe Buffer: 5120 bytes
Input: 5120 bytes
Output: -3 bytes
Die erstellt .xml hat auch wieder 0 Bytes.
 
I

irgendjemand

Gast
also warum du Infalter anstatt einem InflaterInputStream verwendest ... keine ahnung ... werd aus der doc nicht so ganz schlau ...

soweit wie ich das aus der doc lese fehlt 1) Infalter.end() ... und 2) hast du einen kleinen fehler das du versuchst in das selbe array wieder reinzuschreiben aus dem du lesen willst ...

hier solltest du wie in der doc beschrieben zwei arrays nutzen ...

auch hat man das problem mit Infalter das man schlecht in einem loop durch gehen kann ... das sollte mit einem InflaterInputStream einfacher sein ..
 

Zertos

Mitglied
Beziehst du dich auf den Inflater von Java oder von JZLib?

Habe es jetzt mal mit dem InflaterInputStream von Java ausprobiert, aber dann bekomme ich eine ähnliche Exception wie oben.
Java:
Exception in thread "main" java.util.zip.ZipException: incorrect header check
	at java.util.zip.InflaterInputStream.read(Unknown Source)
	at java.io.FilterInputStream.read(Unknown Source)
	at ZLib2.main(ZLib2.java:20)

Hier mal der Testcode. Der Fehler tritt beim Lesen der Datei auf, egal ob ich die Daten gleich in Array schreibe oder nicht:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.util.zip.DeflaterOutputStream;

public class ZLib2
{
	public static void main(String[] args) throws IOException
	{		
		File file = new File("8000-L049.pck");
		InflaterInputStream iis = new InflaterInputStream(new FileInputStream(file));
		DeflaterOutputStream dos = new DeflaterOutputStream(new FileOutputStream(new File(file.getName() + ".xml")));
		byte[] data = new byte[(int)file.length()];
		
		iis.read(data);
	}
}
 
I

irgendjemand

Gast
mal davon abgesehen das dein code da nur wenig sinn ergibt kann es auch sein das du *mit was auch immer* bei der komprimierung einen modus gewählt hast der von java einfach nicht unterstützt wird ...

was ich so gelesen habe soll wohl java.util.zip doch irgendwie eingeschränkt und nicht 100% kompatibel zur zLib sein ...
folglich würde ich behaupten das deine komprimierten daten einfach nicht unterstützt werden ...

JzLib soll da wohl abhilfe schaffen ... aber da es pure java ist kann auch dort nicht 100% alles umgesetzt werden ...

vielleicht versuchst du das ganze einfach noch mal mit anderen komprimierten daten ...

oder versuch den weg mal umgekehrt : komprimiere mal was mit java und versuche es dann mit der gegenstelle *also dem teil womit du die aktuellen daten komprimiert hast* zu dekomprimieren ...
das sollte eigentlich gehen ...

vllt hilft auch google bei der verbindung *da du uns leider nur gesagt hast das du probleme mit dem dekomprimieren der daten unter java hast ... aber nicht womit die daten komprimiert wurden können wir schlecht selbst suchen*
 

Zertos

Mitglied
Der Code war ja nur Testcode und ich hab ihn nicht weitergeschrieben, da der Fehler sowieso schon beim Lesen der Dateien auftritt. ;)

Die .pck Dateien stammen von dem Spiel X3: Terran Conflict und diese sind mit ZLib komprimiert.
Habe für das Spiel ein Tool geschrieben, um in den unkomprimierten .xml Dateien Werte zu verändern und wollte mein Tool noch um die Funktion erweitern, dass die .pck Dateien automatisch dekomprimiert werden und man es nicht manuell mit anderen Tools wie dem X3 Editor machen muss.
Das Problem beim X3 Editor ist nämlich, dass sich dieser nicht per Kommandozeile bedienen lässt, ansonsten würde ich in Java den X3 Editor einfach aufrufen.
 
I

irgendjemand

Gast
davon ausgehend das zLib eh keine system-lib ist dürfte diese also deinem spiel in form einer DLL bei liegen ...

folglich kannst du mit JNA genau diese DLL verwenden um entsprechend der komprimierungs algo die daten auch wieder zu dekomprimieren ...

ansonsten : was macht dich so sicher das die daten mit zLib komprimiert werden ?
 

Zertos

Mitglied
Habe ich von einem Modder für X3 erfahren, dass die Dateien mit ZLib komprimiert wurden.
Außerdem liegt bei dem Spiel auch eine zlib1.dll dabei.
Sollte ich diese benutzen oder die aktuellere Version von ZLib?

Werde es dann mal mit JNA ausprobieren, danke. :)
 
I

irgendjemand

Gast
du solltest erstmal mit JNA versuchen die vorhandene DLL zu verwenden ... würde nämlich sagen das etwas verändert wurde ... ansonsten hättest du ja keine probleme mit java die daten zu dekomprimieren ...
 

Zertos

Mitglied
So, da ich es mit JNA nicht hinbekommen habe bzw. es mir zu viel Arbeit war die ganzen C Klassen in Java zu implementieren, damit die Funktionen funktionieren, habe ich eine andere Möglichkeit gefunden.
Da ja 7Zip auch die ZLib Kompression unterstützt, rufe ich nun das 7za Tool auf, um 7z über Konsolenbefehle zu steuern.
Klappt wunderbar:
Java:
package sevenzip;

import java.io.File;

public class SevenZip
{
	public static void main(String[] args) throws Exception
	{
		String sFile = "C:/Users/Admin/Documents/Dropbox/Eclipse/workspace/JZlib/8000-L049.pck";
		String sevenZipLocation = "D:/Downloads/7za/7za.exe";
		File file = new File(sFile);
		ProcessBuilder builder = new ProcessBuilder(new String[] {sevenZipLocation, "e", sFile});
		builder.start();
		Thread.sleep(500);
		File fileToRename = new File(file.getAbsolutePath().substring(0, (file.getAbsolutePath().length()-4)));
		fileToRename.renameTo(new File(fileToRename.getAbsolutePath() + ".xml"));
	}
}
Und da ich 7za in mein Projekt mit integrieren und releasen darf, ist auch alles in Ordnung. :toll:
 

Oben