Strings komprimieren mit Deflater

javaprogger1987

Erfahrenes Mitglied
Wollte für ein Projekt, wo ich lange ähnliche Strings habe diese mit zip komprimieren.. Bin erst auf die Idee gekommen, als ich die Klasse Deflater endeckt habe.. Aber irgendwie läuft das Beispiel von Sun nich...
compressedDataLength wird immer gleich 0 und in der Doku steht dann dass ich noch zusätzlich Daten in den Buffer schreiben soll.. Muss das eine bestimmte Anzahl an Bytes sein?

Code:
// Encode a String into bytes
String inputString = "blahblahblah";
byte[] input = inputString.getBytes("UTF-8");
// Compress the bytes
byte[] output = new byte[100];
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
int compressedDataLength = compresser.deflate(output);
 
// Decompress the bytes
Inflater decompresser = new Inflater();
decompresser.setInput(output, 0, compressedDataLength);
byte[] result = new byte[100];
int resultLength = decompresser.inflate(result);
decompresser.end();
 
// Decode the bytes into a String
String outputString = new String(result, 0, resultLength, "UTF-8");
 
Hallo!

Schau mal hier:
Code:
/*
 * Created on 18.04.2005@17:27:27
 *
 * TODO Licence info
 */
package de.tutorials;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;

/**
 * @author Darimont
 * 
 * TODO Explain me
 */
public class CompressStringTest {

	public static void main(String[] args) throws Exception {
		String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
		byte[] bytes = str.getBytes("UTF-8");
		int originalSize = bytes.length;
		ByteArrayOutputStream deflatedBytes = new ByteArrayOutputStream();
		DeflaterOutputStream dos = new DeflaterOutputStream(deflatedBytes,
				new Deflater(Deflater.DEFAULT_COMPRESSION));
		dos.write(bytes);
		dos.finish();

		System.out.println("orignal len: " + str.getBytes().length);
		System.out.println("compressed len: " + deflatedBytes.size());

		System.out.println("Compressed String: "
				+ new String(deflatedBytes.toByteArray()));

		InflaterInputStream iis = new InflaterInputStream(
				new ByteArrayInputStream(deflatedBytes.toByteArray()));

		byte[] inflatedBytes = new byte[originalSize];
		iis.read(inflatedBytes);

		System.out.println("Decompressed String: "
				+ new String(inflatedBytes, "UTF-8"));
	}
}

Gruß Tom
 
Ja, das ist eine weitere gute Anwendung für Deflater. Ich hatte das mal für die Serialisierung genutzt.

Wen's interessiert (Anlage): ;-)
 

Anhänge

So das funktioniert schon gut.. Aber hab nun doch noch ein Problem.. Kann es sein, dass die Strings eine Längenbeschränkung haben?


Folgender String löst eine ZipException (Incorrect Data Check) aus:
Code:
	String nc = "0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_";
während

Code:
	String nc = "0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_"+
				"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0_";
dies nicht tut...

Das Problem ist, dass ich so lange Strings brauche...

Oder hättet ihr noch eine andere Idee, wie ich meine Daten speichern könnte:
Ich hab ein Raum (für ein Game) mit ca. 700 Feldern. Nun will ich speichern, was für ein Objekt (Bild) auf jedem Feld ist (0 = nichts). Das ganze kommt dann in eine SQL-Datenbank.. Weil das aber jede Menge Traffic kosten würde wollte ich einfach den komprimierten String in die Datenbank schreiben, und bei Bedarf wieder dekomprimieren..

Ok habs anders gelöst:
Habe "schnuffie"'s FileSaver etwas umgeschrieben, sodass das komprimierte nicht in eine Datei sondern einen ByteArrayOutputStream umgeleitet wird.. Dann hab ich die Strings einfach in ein Array gepackt und es funktioniert :D
Vielen Dank nochmal (andere Lösungsvorschläge nehme ich gerne an ;))

Code:
import java.io.*;
import java.util.zip.*;
public class ObjectCompressor {
  public ObjectCompressor () {
  }
  public byte[] store (Object o) throws IOException {
	Deflater def = new Deflater();
	def.setLevel(Deflater.BEST_COMPRESSION);
	ByteArrayOutputStream deflatedBytes = new ByteArrayOutputStream();
	ObjectOutputStream out = new ObjectOutputStream(
		new DeflaterOutputStream( deflatedBytes, def));
	out.writeObject(o);
	out.close();
	return deflatedBytes.toByteArray();
  }
  public Object load (byte[]ar) throws IOException {
	ObjectInputStream in = new ObjectInputStream(
		new InflaterInputStream(new ByteArrayInputStream( ar ), new Inflater()));
	try {
	  Object o = in.readObject();
	  return o;
	}
	catch (ClassNotFoundException cnfe) {
	  throw new InvalidObjectException(cnfe.getMessage());
	}
	finally {
	  in.close();
	}
  }
}
 
Zuletzt bearbeitet:
javaprogger1987 hat gesagt.:
Oder hättet ihr noch eine andere Idee, wie ich meine Daten speichern könnte:
Ich hab ein Raum (für ein Game) mit ca. 700 Feldern. Nun will ich speichern, was für ein Objekt (Bild) auf jedem Feld ist (0 = nichts). Das ganze kommt dann in eine SQL-Datenbank.. Weil das aber jede Menge Traffic kosten würde wollte ich einfach den komprimierten String in die Datenbank schreiben, und bei Bedarf wieder dekomprimieren..
Hi,
eine Möglichekeit ist nicht jedes Feld speichern zu wollen, Felder die kein Bild beinhalten müssen nicht gespeichert werden. Du muß damit lediglich die Feldstellen (vermutlich Koordinaten) mit dem zu speichernden oder assoziierenden Bild merken.
Das könnte eine Lösung sein wenn Du viele freie Felder hast.

Takidoso
 
Zurück