System.console () gibt null zurück

78

Ich habe readLinevon verwendet BufferedReader, um eine Eingabe / ein neues Passwort vom Benutzer zu erhalten, wollte das Passwort jedoch maskieren, damit ich versuche, die java.io.ConsoleKlasse zu verwenden . Das Problem ist , dass die System.console()Renditen , nullwenn eine Anwendung in Eclipse gedebuggt wird. Ich bin neu in Java und Eclipse. Sind Sie sich nicht sicher, ob dies der beste Weg ist, dies zu erreichen? Ich klicke mit der rechten Maustaste auf die Quelldatei und wähle "Debug As"> "Java Application". Gibt es eine Problemumgehung?

Gallier
quelle
1
Siehe auch stackoverflow.com/questions/26470972/... I identifiziert System.outund System.inals ausreichend für meinen Anwendungsfall und abondaned verwenden System.console().
OneWorld

Antworten:

33

Dieses Code-Snippet sollte den Trick machen:

private String readLine(String format, Object... args) throws IOException {
    if (System.console() != null) {
        return System.console().readLine(format, args);
    }
    System.out.print(String.format(format, args));
    BufferedReader reader = new BufferedReader(new InputStreamReader(
            System.in));
    return reader.readLine();
}

private char[] readPassword(String format, Object... args)
        throws IOException {
    if (System.console() != null)
        return System.console().readPassword(format, args);
    return this.readLine(format, args).toCharArray();
}

Während des Testens in Eclipse wird Ihre Passworteingabe klar angezeigt. Zumindest können Sie testen. Geben Sie beim Testen einfach nicht Ihr echtes Passwort ein. Bewahren Sie das für die Produktion auf;).

Formixian
quelle
Sollte Ihre handgerollte readLineMethode den BufferedReaderBlock endgültig (oder mit Ressourcen versuchen) schließen?
Andrew Swan
Nein, da dies die Übereinstimmung mit dem System.inStream schließen würde und danach kein weiteres Lesen mehr möglich wäre.
Formixian
Ja, es ist seltsam, dass dieser Stream geschlossen werden kann. Ich habe erwartet, dass es ein No-Op wird.
Andrew Swan
8

Ich bin auch auf dieses Problem gestoßen, als ich versucht habe, eine einfache Befehlszeilenanwendung zu schreiben.

Eine andere Alternative zum Erstellen eines eigenen BufferedReader-Objekts aus System.in ist die Verwendung von java.util.Scanner wie folgt:

import java.util.Scanner;

Scanner in;
in = new Scanner(System.in);

String s = in.nextLine();

Dies ist natürlich kein Ersatz für die Konsole, bietet Ihnen jedoch Zugriff auf eine Vielzahl verschiedener Eingabefunktionen.

Hier finden Sie weitere Dokumentationen zu Scanner von Oracle .

MonkeyPaperwork
quelle
7

Laut den Dokumenten :

Wenn die virtuelle Maschine automatisch gestartet wird, z. B. von einem Hintergrundjobplaner, verfügt sie normalerweise nicht über eine Konsole.

Vincent Ramdhanie
quelle
1
Diese Antwort führte mich zu der Feststellung, dass Sie, wenn Sie Gradle mit aktiviertem Deamon ausführen, keine Konsole für Ihre Gradle-Aufgaben erhalten können. Das Ausführen meiner Gradle-Aufgabe mit dem '--no-daemon' ermöglicht den Konsolenzugriff.
Whitespy9
Dies ist mir passiert, als ich drip ( github.com/ninjudd/drip ) für ein Befehlszeilen-Tool verwendet habe. Hoppla!
George L
7

Laut API :

" Wenn die virtuelle Maschine über eine interaktive Befehlszeile gestartet wird, ohne die Standard-Eingabe- und Ausgabestreams umzuleiten, ist ihre Konsole vorhanden und wird normalerweise mit der Tastatur und dem Display verbunden, über die die virtuelle Maschine gestartet wurde. Wenn die virtuelle Maschine gestartet wird automatisch, zum Beispiel von einem Hintergrund-Jobplaner, dann hat er normalerweise keine Konsole. "

Emad Aghayi
quelle
4

Beim Ausführen der Anwendung über Netbeans wurde diese Fehlermeldung angezeigt. Den anderen Antworten nach zu urteilen, scheint dies zu passieren, wenn Sie Ihre Anwendung von einer IDE aus ausführen. Wenn Sie sich diese Frage ansehen: Der Versuch, in Java von der Konsole zu lesen , liegt daran

Die meisten IDEs verwenden javaw.exe anstelle von java.exe, um Java-Code auszuführen

Die Lösung besteht darin, das command line/terminalzu verwenden, um das zu erhalten Console.

Ojonugwa Jude Ochalifu
quelle
1

Ich glaube, dass Sie in den Ausführungskonfigurationen für Eclipse konfigurieren können, ob eine Konsole zugewiesen werden soll oder nicht - stellen Sie sicher, dass dies aktiviert ist. (Es ist schon eine Weile her, dass ich Eclipse verwendet habe, daher kann ich leider keine spezifischen Anweisungen geben).

Wenn dies nicht funktioniert, wird Ihre Anwendung auf jeden Fall im Debug-Modus gestartet und dann mit Eclipse eine Verbindung zum Prozess hergestellt. Suchen Sie nach "Eclipse Remote Debugging", wenn Sie sich nicht sicher sind, wie Sie dies tun sollen.

Darüber hinaus ist es im Allgemeinen eine schlechte Idee, die Zuweisung einer Konsole zu verlangen , da dies die Flexibilität Ihrer Anwendung stark beeinträchtigt - wie Sie gerade festgestellt haben. Auf viele Arten, Java aufzurufen, wird keine Konsole zugewiesen, und Ihre Anwendung ist in diesen Fällen unbrauchbar (was schlecht ist). Vielleicht können Sie auch zulassen, dass Argumente in der Befehlszeile angegeben werden. (Wenn Sie die Konsoleneingabe speziell testen, ist dies fair genug, aber es wäre möglicherweise nützlich, wenn Benutzer Ihre Anwendung über Skripte und / oder auf kopflosen Servern aufrufen können. Daher ist diese Art von flexiblem Design fast immer eine gute Idee Oft führt dies auch zu besser organisiertem Code.)

Andrzej Doyle
quelle
Ja, es ist nur für meinen Debug-Zweck, Benutzer erhalten Shell-Skript oder Bat-Datei. Ist es nicht toll, eine Konsole zu benutzen? Wenn ja, was ist der bessere Weg
Gallier
Übrigens sprechen alle Remote-Debugging-Suchgespräche über den Webserver, aber ich erstelle keine Webanwendung. Dies ist eine einfache Java. könnte eine bessere Möglichkeit sein, das Passwort zu maskieren?
Gallier
Sie können jeden Java-Prozess remote debuggen, indem Sie z. B. -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000die Argumente der VM hinzufügen (zumindest bei Sun JVMs). Die Verwendung der Konsole kann in Ordnung sein, aber wie bereits erwähnt, funktioniert Ihr Code beim Starten ohne eine einfach nicht . Überlegen Sie stattdessen, Werte zu übergeben, die direkt aus Befehlszeilenargumenten, Systemeigenschaften, Eigenschaftendateien usw. stammen. Stellen Sie zumindest eine Alternative bereit - z. B. gehen Sie nur zur Konsole, wenn ein Wert nicht als Befehlszeilenargument angegeben wurde.
Andrzej Doyle
1

Ich habe auf die oben gezeigte Antwort von formixian verwiesen und sie verwendet. Der Punkt ist, die (schwarze) cmd-Konsole zu verwenden, um Ihr Java-Programm wie von "ojonugwa ochalifu" vorgeschlagen auszuführen.

** **.

Park JongBum
quelle
0

Das ist richtig.

Sie müssen die Anwendung außerhalb von Eclipse ausführen. Sehen Sie sich die Launcher-Konfigurationsfenster in Eclipse an und prüfen Sie, ob Sie die Option zum Ausführen des Befehls in einer separaten JVM erkennen können.

Stephen C.
quelle
0

Wenn Ihre IDE Java anstelle von Java verwendet, tritt dieses Problem zwangsläufig auf, da Java im Wesentlichen Java ohne Konsolenfenster ist.

Ingwer Bier
quelle
-1

hinzufügen -console in Ihrem Programm Argumente OSGi - Konsole zu starten

Kane
quelle
1
Können Sie bitte, wenn möglich, ein Beispiel näher erläutern?
Gallier
Ich habe heute etwas Neues gelernt, danke dafür. Eclipse liest die Parameter jedoch weiterhin in der internen Konsole. Ihre vorgeschlagene Lösung löst also nicht das ursprüngliche Problem.
Kiswanij