Unterstützung von java.io.Console in Eclipse IDE

103

Ich verwende die Eclipse-IDE, um meine Java-Projekte zu entwickeln, zu kompilieren und auszuführen. Heute versuche ich, die java.io.ConsoleKlasse zum Verwalten der Ausgabe und vor allem der Benutzereingaben zu verwenden.

Das Problem ist , dass die System.console()Renditen , nullwenn eine Anwendung ausgeführt wird „durch“ Eklipse. Eclipse führt das Programm auf einem Hintergrundprozess aus und nicht auf einem Prozess der obersten Ebene mit dem uns vertrauten Konsolenfenster.

Gibt es eine Möglichkeit, Eclipse zu zwingen, das Programm als Prozess der obersten Ebene auszuführen, oder zumindest eine Konsole zu erstellen, die von der JVM erkannt wird? Andernfalls muss ich das Projekt starten und in einer Befehlszeilenumgebung außerhalb von Eclipse ausführen.

Ross
quelle
Siehe auch stackoverflow.com/questions/26470972/... I identifiziert System.outund System.inals ausreichend für meinen Anwendungsfall und abondaned verwenden System.console().
OneWorld
Ich habe das Projekt als lauffähiges JAR exportiert, aber ich
erhalte

Antworten:

50

Ich gehe davon aus, dass Sie das schrittweise Debuggen von Eclipse verwenden möchten. Sie können die Klassen einfach extern ausführen, indem Sie die erstellten Klassen in den bin-Verzeichnissen im JRE-Klassenpfad festlegen.

java -cp workspace\p1\bin;workspace\p2\bin foo.Main

Sie können mit dem Remote-Debugger debuggen und die in Ihrem Projekt erstellten Klassendateien nutzen.

In diesem Beispiel sieht die Eclipse-Projektstruktur folgendermaßen aus:

workspace\project\
                 \.classpath
                 \.project
                 \debug.bat
                 \bin\Main.class
                 \src\Main.java

1. Starten Sie die JVM-Konsole im Debug-Modus

debug.bat ist eine Windows-Batchdatei, die extern von einer cmd.exe- Konsole ausgeführt werden sollte.

@ECHO OFF
SET A_PORT=8787
SET A_DBG=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=%A_PORT%,server=y,suspend=y
java.exe %A_DBG% -cp .\bin Main

In den Argumenten wurde der Debug-Port auf 8787 gesetzt . Das Argument suspend = y weist die JVM an, zu warten, bis der Debugger eine Verbindung herstellt.

2. Erstellen Sie eine Debug-Startkonfiguration

Öffnen Sie in Eclipse das Dialogfeld "Debuggen" (Ausführen> Dialogfeld "Debuggen öffnen ...") und erstellen Sie eine neue Konfiguration der Remote-Java-Anwendung mit den folgenden Einstellungen:

  • Projekt: Ihr Projektname
  • Verbindungstyp: Standard (Socket Attach)
  • Gastgeber: localhost
  • Hafen: 8787

3. Debuggen

Alles, was Sie tun müssen, wenn Sie die App debuggen möchten, ist:

  • einen Haltepunkt setzen
  • Starten Sie die Batch-Datei in einer Konsole
  • Starten Sie die Debug-Konfiguration

Sie können dieses Problem in Fehler 122429 verfolgen . Sie können dieses Problem in Ihrer Anwendung umgehen, indem Sie eine Abstraktionsschicht verwenden, wie hier beschrieben .

McDowell
quelle
1
Ich würde auch eine pauseam Ende dieser Batch-Datei einfügen, damit Sie alle Fehlermeldungen sehen können, die vor dem Schließen aufblitzen.
Matt Lyons
10
Dies ist der letzte Strohhalm für mich. Wenn ich all dies nur zum Debuggen tun muss, wechsle ich zurück zu Netbeans. So viele nicht behobene Fehler und UI-Belästigungen in Eclipse, dass es nicht einmal lustig ist.
Nuzzolilo
@Nuzzolilo, dies ist nur für das Remote-Debugging. Sie können ohne all das lokal in Eclipse debuggen.
Laplie Anderson
35

Die Problemumgehung, die ich verwende, besteht darin, bei Verwendung von Eclipse nur System.in/System.out anstelle von Console zu verwenden. Zum Beispiel anstelle von:

String line = System.console().readLine();

Sie können verwenden:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line = bufferedReader.readLine();
Laplie Anderson
quelle
20
Ich glaube nicht, dass Sie Passwörter mit Passwortmaskierung auf diese Weise lesen können.
Sualeh Fatehi
3
... und man muss damit umgehen IOException, was bei nicht geworfen wird Console.readLine().
dma_k
5

Der Grund dafür ist, dass eclipse Ihre App als Hintergrundprozess und nicht als Prozess der obersten Ebene mit einer Systemkonsole ausführt.

Heidegrenzen
quelle
5

Sie können eine Klasse selbst implementieren. Es folgt ein Beispiel:

public class Console {
    BufferedReader br;
    PrintStream ps;

    public Console(){
        br = new BufferedReader(new InputStreamReader(System.in));
        ps = System.out;
    }

    public String readLine(String out){
        ps.format(out);
        try{
            return br.readLine();
        }catch(IOException e)
        {
            return null;
        }
    }
    public PrintStream format(String format, Object...objects){
        return ps.format(format, objects);
    }
}
yztaoj
quelle
4

Ich habe etwas dazu unter http://www.stupidjavatricks.com/?p=43 gefunden .

Und da die Konsole endgültig ist, können Sie sie leider nicht erweitern, um einen Wrapper um system.in und system.out zu erstellen, der dies auch tut. Selbst innerhalb der Eclipse-Konsole haben Sie noch Zugriff auf diese. Das ist wahrscheinlich der Grund, warum Eclipse dies noch nicht in ihre Konsole eingesteckt hat ...

Ich verstehe, warum Sie keine andere Möglichkeit haben möchten, eine andere Konsole als System.console ohne Setter zu erhalten, aber ich verstehe nicht, warum Sie nicht möchten, dass jemand die Klasse überschreiben kann, um eine zu erstellen Mock / Testkonsole ...

John Gardner
quelle
4

Eine andere Option besteht darin, eine Methode zu erstellen, um beide Optionen zusammenzufassen, und ein Failover auf die System.in-Methode durchzuführen, wenn die Konsole nicht verfügbar ist. Das folgende Beispiel ist ziemlich einfach: Sie können den gleichen Vorgang ausführen, um die anderen Methoden in der Konsole (readPassword, Format) nach Bedarf zusammenzufassen. Auf diese Weise können Sie es problemlos in Eclipse ausführen. Wenn es bereitgestellt wird, werden die Konsolenfunktionen (z. B. das Ausblenden von Kennwörtern) aktiviert.

    private static String readLine(String prompt) {
        String line = null;
        Console c = System.console();
        if (c != null) {
             line = c.readLine(prompt);
        } else {
            System.out.print(prompt);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            try {
                 line = bufferedReader.readLine();
            } catch (IOException e) { 
                //Ignore    
            }
        }
        return line;
    }
Binärwürfel
quelle
2

Soweit ich das beurteilen kann, gibt es keine Möglichkeit, ein Konsolenobjekt von Eclipse abzurufen. Ich würde nur sicherstellen, dass die Konsole! = Null ist, dann JAR-Datei erstellen und über die Befehlszeile ausführen.

Perimosocordiae
quelle
1

Es scheint keine Möglichkeit zu geben, ein java.io.Console-Objekt abzurufen, wenn eine Anwendung über Eclipse ausgeführt wird. Ein Befehlszeilen-Konsolenfenster wird mit der Anwendung nicht geöffnet, da es als Hintergrundprozess ausgeführt wird (Hintergrund für Eclipse?). Derzeit gibt es kein Eclipse-Plugin, um dieses Problem zu beheben, hauptsächlich aufgrund der Tatsache, dass java.io.Console eine letzte Klasse ist.

Alles, was Sie wirklich tun können, ist, das zurückgegebene Konsolenobjekt auf null zu testen und von dort aus fortzufahren.

Ross
quelle
1

Dieser Link bietet Alternativen zur Verwendung von System.console (). Zum einen wird ein um System.in gewickelter BufferedReader verwendet, zum anderen ein um System.in gewickelter Scanner.

Keiner ist so prägnant wie die Konsole, aber beide arbeiten in Eclipse, ohne auf Debug-Albernheit zurückgreifen zu müssen!

Dave Richardson
quelle
0

Angenommen, Ihr Eclipse-Arbeitsbereich ist C: \ MyWorkspace, Sie haben Ihre Java-Anwendung in einem Maven-Projekt MyProject erstellt und Ihre Java-Hauptklasse ist com.mydomain.mypackage.MyClass.

In diesem Fall können Sie Ihre Hauptklasse ausführen, die System.console()in der Befehlszeile verwendet wird:

java -cp C:\MyWorkspace\MyProject\target\classes com.mydomain.mypackage.MyClass

NB1: Wenn es sich nicht in einem Maven-Projekt befindet, überprüfen Sie den Ausgabeordner in den Projekteigenschaften | Java Build Path | Quelle. Es könnte nicht "Ziel / Klassen" sein

NB2: Wenn es sich um ein Maven-Projekt handelt, sich Ihre Klasse jedoch in src / test / java befindet, müssen Sie wahrscheinlich "target \ test-classes" anstelle von "target \ classes" verwenden.

Paulo Merson
quelle