Prise en charge de java.io.Console dans l'IDE Eclipse

103

J'utilise l'IDE Eclipse pour développer, compiler et exécuter mes projets Java. Aujourd'hui, j'essaie d'utiliser la java.io.Consoleclasse pour gérer la sortie et, plus important encore, l'entrée utilisateur.

Le problème est que System.console()revient nulllorsqu'une application est exécutée "via" Eclipse. Eclipse exécute le programme sur un processus en arrière-plan, plutôt qu'un processus de niveau supérieur avec la fenêtre de console que nous connaissons.

Existe-t-il un moyen de forcer Eclipse à exécuter le programme en tant que processus de niveau supérieur, ou au moins de créer une console que la JVM reconnaîtra? Sinon, je suis obligé de lancer le projet et de l'exécuter sur un environnement de ligne de commande externe à Eclipse.

Ross
la source
Voir aussi stackoverflow.com/questions/26470972/ ... J'ai identifié System.outet System.inpour être suffisant pour mon cas d'utilisation et abandonné l'utilisation System.console().
OneWorld
J'ai exporté le projet en tant que fichier jar exécutable, mais je reçois toujours une erreur nulle de console
Abhigyan

Réponses:

50

Je suppose que vous voulez pouvoir utiliser le débogage pas à pas d'Eclipse. Vous pouvez simplement exécuter les classes en externe en définissant les classes construites dans les répertoires bin sur le chemin de classe JRE.

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

Vous pouvez déboguer à l'aide du débogueur distant et en tirant parti des fichiers de classe intégrés à votre projet.

Dans cet exemple, la structure du projet Eclipse ressemble à ceci:

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

1. Démarrez la console JVM en mode débogage

debug.bat est un fichier de commandes Windows qui doit être exécuté en externe à partir d'une 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

Dans les arguments, le port de débogage a été défini sur 8787 . L' argument suspend = y indique à la JVM d'attendre que le débogueur se connecte.

2. Créez une configuration de lancement de débogage

Dans Eclipse, ouvrez la boîte de dialogue Débogage (Exécuter> Ouvrir la boîte de dialogue de débogage ...) et créez une nouvelle configuration d' application Java distante avec les paramètres suivants:

  • Projet: le nom de votre projet
  • Type de connexion: Standard (Socket Attach)
  • Hôte: localhost
  • Port: 8787

3. Débogage

Donc, tout ce que vous avez à faire à chaque fois que vous souhaitez déboguer l'application est:

  • définir un point d'arrêt
  • lancer le fichier batch dans une console
  • lancer la configuration de débogage

Vous pouvez suivre ce problème dans le bogue 122429 . Vous pouvez contourner ce problème dans votre application en utilisant une couche d'abstraction comme décrit ici .

McDowell
la source
1
Je mettrais également un pauseà la fin de ce fichier de commandes afin que vous puissiez voir tous les messages d'erreur qui clignotent avant sa fermeture.
Matt Lyons
10
C'est la dernière goutte pour moi. Si je dois faire tout cela juste pour déboguer, je reviens à Netbeans. Tant de bugs non résolus et de désagréments liés à l'interface utilisateur dans Eclipse, ce n'est même pas drôle.
nuzzolilo
@Nuzzolilo, c'est juste pour le débogage à distance. Vous pouvez déboguer localement dans eclipse sans tout cela.
Laplie Anderson
35

La solution de contournement que j'utilise consiste simplement à utiliser System.in/System.out au lieu de Console lors de l'utilisation d'Eclipse. Par exemple, au lieu de:

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

Vous pouvez utiliser:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line = bufferedReader.readLine();
Laplie Anderson
la source
20
Je ne pense pas que vous seriez capable de lire les mots de passe avec le masquage de mot de passe de cette façon.
Sualeh Fatehi
3
... et un besoin de manipuler IOException, qui n'est pas jeté en cas de Console.readLine().
dma_k
5

La raison pour laquelle cela se produit est que eclipse exécute votre application en tant que processus d'arrière-plan et non en tant que processus de niveau supérieur avec une console système.

Frontières de la santé
la source
5

Vous pouvez implémenter une classe vous-même. Voici un exemple:

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
la source
4

J'ai trouvé quelque chose à ce sujet sur http://www.stupidjavatricks.com/?p=43 .

Et malheureusement, puisque la console est définitive, vous ne pouvez pas l'étendre pour créer un wrapper autour de system.in et system.out qui le fait non plus. Même dans la console Eclipse, vous avez toujours accès à ceux-ci. C'est probablement pourquoi eclipse n'a pas encore branché cela sur leur console ...

Je comprends pourquoi vous ne voudriez pas avoir un autre moyen d'obtenir une console autre que System.console, sans setter, mais je ne comprends pas pourquoi vous ne voudriez pas que quelqu'un puisse remplacer la classe pour faire un maquette / console de test ...

John Gardner
la source
4

Une autre option consiste à créer une méthode pour encapsuler les deux options et à "basculer" vers la méthode System.in lorsque la console n'est pas disponible. L'exemple ci-dessous est assez basique - vous pouvez suivre le même processus pour résumer les autres méthodes dans la console (readPassword, format) si nécessaire. De cette façon, vous pouvez l'exécuter facilement dans Eclipse et une fois déployé, vous obtenez les fonctionnalités de la console (par exemple, le masquage de mot de passe).

    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;
    }
cube binaire
la source
2

Pour autant que je sache, il n'y a aucun moyen d'obtenir un objet Console d'Eclipse. Je m'assurerais juste que la console! = Null, puis la JAR et l'exécuterais à partir de la ligne de commande.

perimosocordiae
la source
1

Il semble qu'il n'y ait aucun moyen d'obtenir un objet java.io.Console lors de l'exécution d'une application via Eclipse. Une fenêtre de console de ligne de commande n'est pas ouverte avec l'application, car elle est exécutée en tant que processus d'arrière-plan (arrière-plan d'Eclipse?). Actuellement, il n'y a pas de plugin Eclipse pour gérer ce problème, principalement en raison du fait que java.io.Console est une classe finale.

Tout ce que vous pouvez vraiment faire est de tester l'objet Console renvoyé pour null et de continuer à partir de là.

Ross
la source
1

Ce lien propose des alternatives à l'utilisation de System.console (). La première consiste à utiliser un BufferedReader enroulé autour de System.in, la seconde consiste à utiliser un Scanner enroulé autour de System.in.

Ni l'un ni l'autre ne sont aussi concis que la console, mais les deux fonctionnent en éclipse sans avoir à recourir à la bêtise de débogage!

Dave Richardson
la source
0

Supposons que votre espace de travail Eclipse soit C: \ MyWorkspace, vous avez créé votre application java dans un projet maven MyProject et votre classe principale Java est com.mydomain.mypackage.MyClass.

Dans ce cas, vous pouvez exécuter votre classe principale qui utilise System.console()sur la ligne de commande:

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

NB1: si ce n'est pas dans un projet maven, vérifiez le dossier de sortie dans les propriétés du projet | Chemin de construction Java | La source. Ce n'est peut-être pas "cible / classes"

NB2: s'il s'agit d'un projet maven, mais que votre classe est dans src / test / java, vous devrez probablement utiliser "target \ test-classes" au lieu de "target \ classes"

Paulo Merson
la source