Java Textdateien und binäre Daten in einer Datei abspeichern

CPU

Lieutenant
Registriert
Jan. 2006
Beiträge
704
Hallo,

ich habe folgendes Problem: ich habe einige Textdateien, welche u.U. "Anhänge" (Zip-Archive, Bilder etc.) besitzen.
Und ich möchte diese Textdateien und die Anhänge in einer Datei mit meinem Java-Programm speichern. Dabei sollen die Java-Libs, die ich einbinden muss sehr klein bleiben (~ 500 kb).

Diese Lösungsmöglichkeiten habe ich bereits gefunden:

* Java-Serialisierung: Objekte beinhalten Text-Dateien als STRING-Wert und die Anhänge werden in einem BYTE[]-Feld beinhaltet. => Sehr langsam; muss erst alles geladen werden u.ä.

* Zip-Archive mit Java: eigentlich ideal. Leider kann man keine Dateien einfach hinzufügen.

* SQLJet: möglich, jedoch Libs größer 500 kb (~ 1000 kb).

Vielleicht kennt Ihr ja eine gute Möglichkeit ...

Gruß,
CPU
 
Du könntest Dir ein sehr einfaches eigenes Dateiformat überlegen und dieses dann direkt mit Outputstream schreiben, z.b. sowas

1 byte - Kennung, dass Textdatei folgt
4 bytes - Länge der folgenden Textdatei
x bytes - Die Textdatei selbst

1 byte - Kennung, dass Anhang folgt, welche zur letzten Textdatei gehört
4 bytes Länge des anhangs
...
1 byte - Kennung, dass Anhang folgt, welche zur letzten Textdatei gehört
4 bytes Länge des Anhangs

Das ganze könntest du dann noch mit einem GzipOutputStream kombinieren, dann werden die Datei auch noch komprimiert.


Dieser lösung bedarf gar keiner externen Bibliotheken.
 
Hallo,

Ja, ich weiß, dass es nicht so gerne gesehen wird, wenn man alte Beiträge nochmals hervorkramt!
Dennoch bin ich beim aufräumen über diesen Beitrag von mir gestolpert. Jetzt erscheint mir das alles irgendwie "spannender". K.A. was damals mit mir los war :-)

Nun gut. Ich habe mal schnell nach Anleitung von Banthor was gebastelt (siehe unten). Aber es fehlt mir ja noch die ein oder andere Information, da ich ein Neuling auf dem Gebiet des "rohen" OutputStreams bin!

Worauf muss ich z.B. achten? Wie mache ich das mit den Zeichensätzen (siehe mein Ahnang), dass die nicht zerstört werden? Wie ist das mit der Laufzeit für große Dateien? Wie kann man optimieren?

Beste Grüße,
CPU

P.S.: Einen Guten Rutsch Euch allen!

Code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class TestWrite {
	
	public static void main(String[] args) throws Exception {
		
		// SCHREIBEN
		
		OutputStream os = new FileOutputStream(new File("test.dat"));
		
		String s = "Dies ist ein schöner Text!";
		
		os.write(0xFF);
		os.write(s.getBytes().length);
		os.write(s.getBytes());
		
		os.write(0xFE);
		byte[] attach = new byte[]{0x00, 0x01, 0x02, 0x03};
		os.write(attach.length);
		os.write(attach);
		
		
		os.flush();
		os.close();
		
		// AUSLESEN
		
		InputStream is = new FileInputStream(new File("test.dat"));
		
		int b = is.read();
		System.out.println(b + " (Ist Anfangsmarker? " + (b == 0xFF) + ")");
		System.out.println();
		
		int lenText = is.read();
		System.out.println("Textlaenge: " + lenText);
		for (int i = 0; i < lenText; i++) {
			System.out.print((char) is.read());
		}
		System.out.println();
		System.out.println();
		
		b = is.read();
		System.out.println(b + " (Ist Anhangsmarker? " + (b == 0xFE) + ")");
		
		int lenAttach = is.read();
		System.out.println("Laenge Anhang: " + lenAttach);
		for (int i = 0; i < lenAttach; i++) {
			System.out.print(is.read());
			if (i < lenAttach-1) {
				System.out.print(", ");
			}
		}
		System.out.println();
	}
	
}
 
CPU schrieb:
Zip-Archive mit Java: eigentlich ideal. Leider kann man keine Dateien einfach hinzufügen.

Definiere "einfach"? Mehr als 20 Zeilen Code braucht es hierfür wohl nicht. Ist es für Dich zu schwierig, das umzusetzen?

Wenn man die externen Abhängigkeiten nicht scheut, kann man auch Libs wie Apache Commons nutzen.
 
soares schrieb:
Definiere "einfach"? Mehr als 20 Zeilen Code braucht es hierfür wohl nicht. Ist es für Dich zu schwierig, das umzusetzen?

Nun, das stimmt schon. Ich kann das auch alles. Nur hat ja ZIP in Java einen Haken: wenn ich eine Datei zu einem bestehenden ZIP-Archiv hinzufügen möchte, dann muss ich ein neues erstellen und die alten Dateien plus die neue(n) hineispeichern. Und das ist mir von der Performance zu aufwändig!

Gruß,
CPU
 
Um das Laden der Zip-Files kommst Du in Java nicht herum. TrueZip soll recht performant sein. Allerdings weiß nicht, wie das umgesetzt ist. Möglicherweise geht es schneller.

Wenn es nicht schnell genug zu bewerkstelligen ist, musst Du Dir in der Tat etwas eigenes stricken oder auf native Tools ausweichen.

Hast Du gemessen, dass es zu langsam ist? Oder denkst Du nur, es ist nicht schnell genug? Wie groß sind Deine Zip-Dateien im Durchschnitt?
 
Um auf deine eigentlich Frage zurückzukommen:

Du verwendest s.getBytes() ohne Parameter. In diesem Fall wird das default charset verwendet, welches im schlimmsten Fall deine Zeichen schrottet. Es kann auch passieren, dass eine unter Windows geschriebene Datei dann unter einem anderen OS nicht mehr korrekt eingelesen wird, weil dort ein anderes default encoding besteht.

Verwende daher lieber s.getBytes("UTF-8"), dann wird immer das gleiche Encoding verwendet, gleichzeitig kannst du Dir sicher sein, dass die Zeichen erhalten bleiben.

Dann habe ich gesehen, dass du s.getBytes zweimal aufrufst. Mach das nicht, weil das Array sonst zwei mal erzeugt wird. Ruf es einmal auf un merke dir das Ergebnis.


Dann zu den Dateigrößen: Es hält Dich nichts davon ab den Outputstream zusätzlich zu zippen, dann sind die Dateien schön klein, wenn sehr viel Text enthalten ist.

EDIT:

Kleiner Nachtrag:
Ich sehe dass das Einlesen nicht korrekt ist. Du solltest nicht charweise lesen, sondern erzeuge ein byte[] mit der Länge die zu zuvor gelesen hast. Dann gibt es bei STring einen Spezialkonstruktor, mit dem Du die Bytes unter angabe des Charsets "UTF-8" dann wieder in einen String wandeln kannst.

Das ist sehr wichtig, weil bei UTF-8 nicht jedes Byte einem Zeichen entsprechen muss, es können auch mal 2 oder mehr Bytes pro Zeichen sein, wenn Sonderzeichen oder Umlaute auftauchen. Wenn du nur ein char einliest, dann wird das nicht berücksichtigt.
 
Zuletzt bearbeitet:
Zurück
Oben