supporto java.io.Console in Eclipse IDE


103

Uso l'IDE Eclipse per sviluppare, compilare ed eseguire i miei progetti Java. Oggi sto cercando di utilizzare la java.io.Consoleclasse per gestire l'output e, cosa più importante, l'input dell'utente.

Il problema è che System.console()ritorna nullquando un'applicazione viene eseguita "tramite" Eclipse. Eclipse esegue il programma su un processo in background, piuttosto che un processo di primo livello con la finestra della console che conosciamo.

C'è un modo per forzare Eclipse a eseguire il programma come processo di primo livello, o almeno creare una console che la JVM riconoscerà? Altrimenti, sono costretto a eseguire il jar del progetto ed eseguire su un ambiente a riga di comando esterno a Eclipse.


Vedi anche stackoverflow.com/questions/26470972/… Ho identificato System.oute System.inper essere sufficiente per il mio caso d'uso e ho abbandonato l'utilizzo System.console().
OneWorld

Ho esportato il progetto come jar eseguibile, ma ricevo ancora l'errore nullo della console
Abhigyan

Risposte:


50

Presumo che tu voglia essere in grado di utilizzare il debug passo-passo da Eclipse. È possibile eseguire le classi esternamente impostando le classi costruite nelle directory bin sul percorso di classe JRE.

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

Puoi eseguire il debug utilizzando il debugger remoto e sfruttando i file di classe incorporati nel tuo progetto.

In questo esempio, la struttura del progetto Eclipse ha questo aspetto:

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

1. Avviare la console JVM in modalità di debug

debug.bat è un file batch di Windows che dovrebbe essere eseguito esternamente da una console cmd.exe .

@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

Negli argomenti, la porta di debug è stata impostata su 8787 . L' argomento suspend = y indica alla JVM di attendere finché il debugger non si collega.

2. Creare una configurazione di avvio di debug

In Eclipse, apri la finestra di dialogo Debug (Esegui> Apri finestra di dialogo Debug ...) e crea una nuova configurazione dell'applicazione Java remota con le seguenti impostazioni:

  • Progetto: il nome del tuo progetto
  • Tipo di connessione: standard (attacco presa)
  • Host: localhost
  • Porta: 8787

3. Debug

Quindi, tutto ciò che devi fare ogni volta che vuoi eseguire il debug dell'app è:

  • impostare un punto di interruzione
  • avviare il file batch in una console
  • avvia la configurazione di debug

Puoi tenere traccia di questo problema nel bug 122429 . È possibile aggirare questo problema nella propria applicazione utilizzando un livello di astrazione come descritto qui .


1
Metterei anche un pausealla fine di quel file batch in modo da poter vedere eventuali messaggi di errore che lampeggiano prima che si chiuda.
Matt Lyons

10
Questa è l'ultima goccia per me. Se devo fare tutto questo solo per eseguire il debug, torno a Netbeans. Così tanti bug non risolti e fastidi dell'interfaccia utente in Eclipse non è nemmeno divertente.
nuzzolilo

@Nuzzolilo, questo è solo per il debug remoto. Puoi eseguire il debug localmente in eclipse senza tutto ciò.
Laplie Anderson

35

La soluzione alternativa che utilizzo è utilizzare semplicemente System.in/System.out invece di Console quando si utilizza Eclipse. Ad esempio, invece di:

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

Puoi usare:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line = bufferedReader.readLine();

20
Non credo che saresti in grado di leggere le password mascherando la password in questo modo.
Sualeh Fatehi

3
... e una necessità da gestire IOException, che non viene lanciata in caso di Console.readLine().
dma_k

5

Il motivo per cui ciò si verifica è perché eclipse esegue la tua app come processo in background e non come processo di primo livello con una console di sistema.


5

Puoi implementare una classe da solo. Di seguito è riportato un esempio:

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);
    }
}

4

Ho trovato qualcosa al riguardo su http://www.stupidjavatricks.com/?p=43 .

E purtroppo, poiché la console è definitiva, non puoi estenderla per creare un wrapper attorno a system.in e system.out che lo fa. Anche all'interno della console di eclipse hai ancora accesso a quelli. Questo è probabilmente il motivo per cui eclipse non l'ha ancora collegato alla loro console ...

Capisco perché non vorresti avere un altro modo per ottenere una console diversa da System.console, senza setter, ma non capisco perché non vorresti che qualcuno fosse in grado di sovrascrivere la classe per creare un console di simulazione / test ...


4

Un'altra opzione è creare un metodo per racchiudere entrambe le opzioni e "eseguire il failover" al metodo System.in quando Console non è disponibile. L'esempio seguente è abbastanza semplice: puoi seguire lo stesso processo per riassumere gli altri metodi in Console (readPassword, format) come richiesto. In questo modo puoi eseguirlo felicemente in Eclipse e quando viene distribuito ottieni le funzionalità della console (ad esempio nascondere la password).

    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;
    }

2

Per quanto ne so, non c'è modo di ottenere un oggetto Console da Eclipse. Mi assicurerei solo che la console! = Null, quindi JAR e eseguirlo dalla riga di comando.


1

Non sembra esserci alcun modo per ottenere un oggetto java.io.Console quando si esegue un'applicazione tramite Eclipse. Una finestra della console della riga di comando non viene aperta con l'applicazione, poiché viene eseguita come processo in background (in background per Eclipse?). Al momento, non esiste un plug-in Eclipse per gestire questo problema, principalmente perché java.io.Console è una classe finale.

Tutto quello che puoi fare è testare il valore nullo dell'oggetto Console restituito e procedere da lì.


1

Questo collegamento offre alternative all'utilizzo di System.console (). Uno è usare un BufferedReader avvolto attorno a System.in, il secondo è usare uno Scanner avvolto attorno a System.in.

Nessuno dei due è conciso come la console, ma entrambi funzionano in eclipse senza dover ricorrere alla stupidità del debug!


0

Supponiamo che il tuo spazio di lavoro Eclipse sia C: \ MyWorkspace, hai creato la tua applicazione java all'interno di un progetto maven MyProject e la tua classe principale Java è com.mydomain.mypackage.MyClass.

In questo caso, puoi eseguire la tua classe principale che utilizza System.console()sulla riga di comando:

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

NB1: se non è in un progetto Maven, controlla la cartella di output nelle proprietà del progetto | Percorso build Java | Fonte. Potrebbe non essere "target / classes"

NB2: se è un progetto maven, ma la tua classe è in src / test / java, probabilmente dovrai usare "target \ test-classes" invece di "target \ classes"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.