Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Ich verstehe nicht warum eine Exception nicht in mein catch block reinspringt. Die Exception FileNotFound wird in Zeile 19 geworfen und müsste eigentlich von dem IOException catch Block in Zeile 21 abgefangen werden. Passiert aber nicht.
Ich möchte einen Hinweis einblenden, wenn der Benutzer Blödsinn in das Eingabefeld des JFileChooser eintippt (z.B. !“§1234§/?). In diesem Fall wird von Java die Exception FileNotFound auf der Konsole angezeigt und das Bild wird nicht gespeichert, der Benutzer bekommt von dem alles nichts mit. Deshalb möchte ich diese abfangen und im catch Block ein Dialog öffnen.
der String der URL wird korrekt zusammengefügt: Der sieht z.B so aus:C:\Users\jabby\!“§1234§/?.png.
Java:
private void saveImage() {
// System.out.println("save Image");
File url = view.showSaveChooser();
BufferedImage saveImg = model.getPictureAtIndex(index);
try{
if (url.toString().toLowerCase().endsWith(".jpg")) {
ImageIO.write(saveImg, "jpg", url);
} else if (url.toString().toLowerCase().endsWith(".png")) {
ImageIO.write(saveImg, "png", url);
} else if (url.toString().toLowerCase().endsWith(".bmp")) {
ImageIO.write(saveImg, "bmp", url);
} else if (url.toString().toLowerCase().endsWith(".gif")) {
ImageIO.write(saveImg, "gif", url);
}else{
//Wenn kein Dateityp eingegeben, dann png format.
String url1=url.toString()+".png";
ImageIO.write(saveImg, "png", new File(url1));
}
}catch(IOException e){
System.out.println("Fehler beim schreiben");
}
}
Die Exception:
Java:
java.io.FileNotFoundException: C:\Users\jabby\!".png (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(Unknown Source)
at javax.imageio.stream.FileImageOutputStream.<init>(Unknown Source)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(Unknown Source)
at javax.imageio.ImageIO.createImageOutputStream(Unknown Source)
Wenn die Exception wirklich in Zeile 19 geworfen wird, dann sprint er 100%ig auch in den catch Block. Bist du dir sicher dass die Exception nicht woanders fliegt, ich seh da noch keine Zeilenangabe?
Ja, ich bin mir ziemlich sicher. Das steht auch in der Exception. Hier die komplette Ausgabe:
Java:
java.io.FileNotFoundException: C:\Users\jabby\!".png (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(Unknown Source)
at javax.imageio.stream.FileImageOutputStream.<init>(Unknown Source)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(Unknown Source)
at javax.imageio.ImageIO.createImageOutputStream(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at de.ba.imageprocessing.controller.PGUI.saveImage(PGUI.java:137)
at de.ba.imageprocessing.controller.PGUI.actionPerformed(PGUI.java:84)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.imageio.ImageIO.write(Unknown Source)
at de.ba.imageprocessing.controller.PGUI.saveImage(PGUI.java:137)
at de.ba.imageprocessing.controller.PGUI.actionPerformed(PGUI.java:84)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Hier wird auf Zeile 137 verwiesen. Das entspricht der Zeile 19 im obrigen Beispiel.
In Zeile 84 wird die Methode in actionperformed aufgerufen. Ich habe den try-catch Block auch dort ausprobiert.Leider vergebens....
also dein Vorschlag funktioniert leider auch nicht.
Java:
else{
//Wenn kein Dateityp eingegeben, dann png format.
try{
String url1=url.toString()+".png";
ImageIO.write(saveImg, "png", new File(url1));
}catch(IOException e){
System.out.println("Fehler");
}
}
Der Debugger gibt auch an dieser Stelle die Meldung und das Programm läuft weiter. Ich habe auch schon versucht die Exception mit "throws" an der Stelle abzufangen, an der die Methode aufgerufen wird.
wenn er in Zeile 19 bzw 137 (lt. Stacktrace) eine FileNotFoundException wirft, wird er auf den Standardoutput "Fehler beim Schreiben" ausgeben und danach ganz normal im Programmablauf mit der Zeile 85 aus deiner actionPerformed-Methode weiter. Dort sehe ich leider nirgendwo das Öffnen eines Dialoges. Sollte dies weiter oben im Trace passieren (also in der actionPerformed zum Beispiel) kommt die Exception dort nicht an, weil sie nach Abarbeitung des catch-Blockes aus den Zeilen 22 - 24 (im Quellcodeblock aus deinem Eingangsposting) verworfen wird.
java.io.FileNotFoundException: !"$%&/%$ (No such file or directory)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:233)
at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:69)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:55)
at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:409)
at javax.imageio.ImageIO.write(ImageIO.java:1520)
at Main.main(Main.java:12)
FEHLER!!!!
Die FileNotFoundException wird tatsächlich nicht gefangen, die wird vermutlich irgendwo in den Tiefen von ImageIO verarbeitet und auf den Errorstream gegeben.
Du müsstest also vorher prüfen ob der Dateiname gültig ist.
(
Code:
Fehler!!!!
wird ausgegeben weil da noch ne NullPointerException fliegt).
[EDIT]@EikeB
mist ... zu langsam ... ich geb auf xD
aber zumindest mal ein klärender einblick in die API wo die NPE herkommt ...[/EDIT]
da zwar die NPE kein cause für die FNFE ist ... aber beide auf zeile 137 verweisen ... würde ich entweder vor dem try-catch mal mit if() prüfen ob "url" und "saveImg" NULL sind ... also [c]if(url==null||saveImg==null)[/c] bzw einen zweiten catch-block für NPE unten dran hängen [c]catch(NullPointerException npe) { npe.printStackTrace(); }[/c] ...
so könntest du dann schon mal den grund für die NPE rausbekommen ...
wenn du ganz finster bist könntest du den JFileChooser soweit "hacken" und dem JTextField ein verändertes PlainDocument zuweisen welches als input nur gültige zeichen [a-zA-Z0-9\\-_] annimmt ... aber ich glaube das würde hier jetzt zu weit führen ... *nur mal so als theoretischen ansatz was möglich wäre*
auch solltest du folgendes beachten : I/O operationen sollten NIE im EDT ausgeführt werden ...
woher wir wissen das es so ist : 1) der stack "AWT-EventQueue-0" 2) der dierekte call in "actionPerformed()" ...
sowas sollte IMMER einen einen eigenen thread ausgelagert werden ....
was es allerdings mit diesem "index" auf sich hat ... hmm ... den könnte man auch mal auf gültigkeit prüfen ... wäre auch mal interessant zu wissen wo der herkommt und wie dieser ermittelt wird ... sieht mir nämlich nach ner unsauber implementierten instanz-variable aus ... -> lieber als parameter der methode ...
alles in allem sehr komisches verhalten mit eigentlich eindeutigen stacks ...
ich glaube hier wäre echt ein KSKB oder *da es ja nicht viel code zu sein scheint* der komplette code nützlich damit man da mal selbst debuggen könnte ...
Danke für eure ausführlichen Erklärungen und Bemühungen.
Noch kurz zum EDT: Mir ist der Begriff noch etwas schwammig. Für mich hat der EDT die Aufgabe, die Abarbeitung der Events zu überprüfen (besonders der von Swings, weil einige ja nicht Thread sicher sind). Also steht der EDT immer im Zusammenhang mit beispielsweise ActionListener, actionPerformed().
Langfristige Berechnungen (bspw. IO-Operationen) in actionPerformed() müssen ausgelagert werden und asynchron laufen, damit man die GUI nicht blockiert(was der EventDispatcherThread nach meinem Kenntnisstand macht). Für die asynchrone Abarbeitung erbt man von Thread und implentiert die run() methode.
Nun zu meinem Fall:
Ich habe mir eine Controller Klasse programmiert, die alle Events von der View abfängt und anhand von ActionCommands die jeweiligen Methode aufruft (z.B. saveImage, die in der Controller Klasse implementiert ist). Ich habe es verstanden, dass es so schlecht programmiert ist .
Was mir unschlüssig ist diese Bemerkung von irgendjemand
der dierekte call in "actionPerformed()" ... sowas sollte IMMER einen einen eigenen thread ausgelagert werden ....
:
Wie würde das in meinem Fall aussehen. Die Methoden im Controller einfach in die run() Methode packen und die Sache ist erledigt oder ist noch etwas komplizierter? Was auch für mich neu ist, ist die Klasse SwingWorker. Ist das besser zum Auslagern und für Threads?
Ich schweife zwar etwas vom Thema ab, aber das würde mich noch gerne interessieren.
der EDT hat nicht die aufgabe irgendwas zu prüfen ...
der EDT ist lediglich ein deamon-thread welcher bei einer GUI den user-input auffängt und an die jeweilige component und ihre listener weiterleitet ... nicht mehr und nicht weniger ... nix mit kontrolle ... lediglich ausführung
auch ist deine vermutung das der EDT angeblich von selbst alles in seperaten threads ausführt falsch
wenn der EDT z.b. den maus-klick auf einen JButton bemerkt ... so löst er ein ActionEvent auf dessen listener aus ... das passiert aber alles dierekt im EDT ... und somit läuft auch der gesamte code der in irgendeinem listener steht im EDT ab ...
um also nun das was erledigt werden soll in einen eigenen , seperaten vom EDT unabhängigen thread auszulagern entweder SwingUtilities verwenden oder eine eigene klasse schreiben welche von Thread erbt und dann darauf start() callen ...
z.b. so
Java:
public void actionPerformed(ActionEvent e)
{
(new DeineVonThreadAbgeleiteteKlasse(e)).start();
}
wie ich in meinem EDIT angemerkt habe : dank EikeB wissen wir nun woher 1) der StackTrace kommt und 2) woher die NPE kommt ...
ergo musst du dem vorbeugen wenn du diese "fehler" weg haben willst ...
was nun mal am einfachsten geht in dem du das was vom JFileChooser geliefert wird selbst überprüfst *RegEx sind hier ne gute wahl*
@EikeB/Irgendjemand: SwingUtilities.invokeLater und SwingUtilities.invokeAndWait führen das übergebene Runnable im EDT aus. Um etwas nicht im EDT auszuführen sollte man SwingWorker verwenden oder selbst einen Thread erstellen. SwingUtilites benötigt man wenn man aus dem Anwendungsthread heraus dann die GUI wieder ändern will.