In JAR gepackte PDF-Datei ausführen

miffi

Erfahrenes Mitglied
Hallo zusammen.

Nach langer, verzweifelter Suche habe ich mich mal hier registriert und hoffe, ihr könnt mir weiterhelfen.

Folgendes Problem:
Ich habe für meine Diplom-Arbeit eine Java-Anwendung geschrieben, die am Ende als ausführbares JAR gepackt werden soll. Alles läuft soweit einwandfrei, bis auf den User-Guide, den ich als PDF in Tex geschrieben habe.

Um das PDF überhaupt ausführbar zu machen, benutze ich eine temporäre Datei, die mit folgendem Code erstellt wird:
Code:
InputStream input = ClassLoader.getSystemResourceAsStream(this.userGuideURL);
byte[] inputBits = new byte[input.available()];
input.read(inputBits);
input.close();
		  	
this.userGuideFile = File.createTempFile("UserGuide", ".pdf");
this.userGuideFile.deleteOnExit();
	        
FileOutputStream output = new FileOutputStream(this.userGuideFile);
output.write(inputBits);
output.flush();
output.close();

Wird nun über das Menü die Hilfe aufgerufen, wird folgender Code ausgeführt:
Code:
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + this.userGuideFile.getAbsolutePath());

Führe ich die Anwendung aus dem Eclipse-Workspace aus, klappt alles einwandfrei. Starte ich die Hilfe jedoch aus dem JAR, wird die temporäre Datei zwar erzeugt, ist jedoch fehlerhaft, also vom Acrobar Reader nicht lesbar. Die Dateigröße der temporären Datei ist identisch mit der originalen.

Kennt jemand dieses Problem und kennt vielleicht sogar eine Lösung?

MfG,
miffi
 
input.available sagt dir nur wieviele Bytes gerade im Stream sind. Das hat aber nichts damit zu tun wie groß die Datei tatsächlich ist. Normalerweise macht man es so, dass man sich einen Buffer mit sinnvoller größer definiert und aus dem Input in diesen Puffer einliest und die gelesenen Daten in den Output schreibt. Und das so lange bis man am Ende angekommen ist (-1).

Also so in etwa:

Java:
final byte[] buffer = new byte[1024];

InputStream input = ClassLoader.getSystemResourceAsStream(this.userGuideURL);
this.userGuideFile = File.createTempFile("UserGuide", ".pdf");
this.userGuideFile.deleteOnExit();
	        
FileOutputStream output = new FileOutputStream(this.userGuideFile);

int read;
while((read = input.read(buffer)) != -1){
   output.write(buffer, 0, read);
}
input.close();
output.close();

Achja: Wenn du aktuelles Java 6 verwenden darfst dann kannst du zum öffnen der Datei auch Desktop.open(userGuideFile) verwenden. Das geht dann auch auf anderen Betriebssystemen.
 
Erstmal vielen Dank für die schnelle Antwort, zeja :)

@Desktop.getDesktop(...):
Das ist super, da ich ohnehin Java 1.6 verwende und meine Applikation wirklich plattformunabhängig ist jetzt.

@Deine Lösung mit buffer:
Es leuchtet mir ein, was du schreibst, ABER:
  1. Warum hat meine Lösung dann funktioniert, wenn ich das Ganze aus dem Workspace ausführe?
  2. Mit deiner Lösung funktionierts jetzt auch im Workspace nicht mehr... Selber Fehler wie vorher im JAR
 
Warum das im eclipse funktioniert hat: Keine Ahnung aber wenn du mal in die API schaust steht da auch zu available:

Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.

Hast du das jetzt exakt so stehen wie ich das geschrieben habe? Hast du die Exceptions entsprechend behandelt?
 
Ja, hab ich auch gelesen... Da hab ich mich in der Hektik nur vertan. Mich wundert halt, dass es funktioniert hat...

Und ja, ich hab es genau von dir übernommen:
Code:
    try {
	InputStream input = ClassLoader.getSystemResourceAsStream(this.dataURL + this.userGuideURL);
	byte[] inputBits = new byte[input.available()];
	input.read(inputBits);
		  	
	this.userGuideFile = File.createTempFile("UserGuide", ".pdf");
	this.userGuideFile.deleteOnExit();
	        
	final byte[] buffer = new byte[1024];
	int read;
	FileOutputStream output = new FileOutputStream(this.userGuideFile);
	        
	 while((read = input.read(buffer)) != -1){
	       output.write(buffer, 0, read);
	  }
	  input.close();
	  output.close();
      } catch (IOException e) {
	        e.printStackTrace();
}

Und die Größe der temporären Datei stimmt übrigens nicht mehr. Muss ich bei der Puffer-Größe irgendwas beachten?
 
Du hast da oben noch was vergessen:

Java:
InputStream input = ClassLoader.getSystemResourceAsStream(this.dataURL + this.userGuideURL);
byte[] inputBits = new byte[input.available()];
input.read(inputBits);

Da liest du schon nen Stück. Das fehlt dir dann natürlich nachher.

Wenn du statt code einfach Java in die Tags schreibst, hast du das Syntax-Highlighting für Java.
 
Du hast da oben noch was vergessen:
Da liest du schon nen Stück. Das fehlt dir dann natürlich nachher.

Wenn du statt code einfach Java in die Tags schreibst, hast du das Syntax-Highlighting für Java.
Ich Trottel....
Vor lauter Betriebs-Blindheit völlig übersehen. Also, es funktioniert jetzt auch im JAR.

Vielen vielen Dank für deine Hilfe :)
 

Neue Beiträge

Zurück