Soporte java.io.Console en Eclipse IDE

103

Utilizo el IDE de Eclipse para desarrollar, compilar y ejecutar mis proyectos Java. Hoy, intento usar la java.io.Consoleclase para administrar la salida y, lo que es más importante, la entrada del usuario.

El problema es que System.console()vuelve nullcuando se ejecuta una aplicación "a través" de Eclipse. Eclipse ejecuta el programa en un proceso en segundo plano, en lugar de un proceso de nivel superior con la ventana de la consola con la que estamos familiarizados.

¿Hay alguna forma de obligar a Eclipse a ejecutar el programa como un proceso de nivel superior, o al menos crear una consola que la JVM reconocerá? De lo contrario, me veo obligado a activar el proyecto y ejecutarlo en un entorno de línea de comandos externo a Eclipse.

Ross
fuente
También vea stackoverflow.com/questions/26470972/… Identifiqué System.outy System.inpara ser suficiente para mi caso de uso y aboné el uso System.console().
OneWorld
Exporté el proyecto como el jar ejecutable, pero sigo recibiendo el error nulo de la consola
Abhigyan

Respuestas:

50

Supongo que desea poder utilizar la depuración paso a paso de Eclipse. Puede ejecutar las clases externamente configurando las clases compiladas en los directorios bin en la ruta de clases de JRE.

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

Puede depurar usando el depurador remoto y aprovechar los archivos de clase integrados en su proyecto.

En este ejemplo, la estructura del proyecto Eclipse se ve así:

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

1. Inicie la consola JVM en modo de depuración

debug.bat es un archivo por lotes de Windows que debe ejecutarse externamente desde una consola 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

En los argumentos, el puerto de depuración se ha establecido en 8787 . El argumento suspend = y le dice a la JVM que espere hasta que el depurador se conecte.

2. Cree una configuración de inicio de depuración

En Eclipse, abra el cuadro de diálogo Depurar (Ejecutar> Abrir cuadro de diálogo de depuración ...) y cree una nueva configuración de Aplicación Java remota con la siguiente configuración:

  • Proyecto: el nombre de su proyecto
  • Tipo de conexión: estándar ( conexión de enchufe)
  • Anfitrión: localhost
  • Puerto: 8787

3. Depuración

Entonces, todo lo que tiene que hacer cada vez que desee depurar la aplicación es:

  • establecer un punto de quiebre
  • lanzar el archivo por lotes en una consola
  • lanzar la configuración de depuración

Puede rastrear este problema en el error 122429 . Puede solucionar este problema en su aplicación utilizando una capa de abstracción como se describe aquí .

McDowell
fuente
1
También pondría un pauseal final de ese archivo por lotes para que pueda ver los mensajes de error que aparecen antes de que se cierre.
Matt Lyons
10
Esta es la última gota para mí. Si tengo que hacer todo esto solo para depurar, volveré a Netbeans. Tantos errores sin corregir y molestias en la interfaz de usuario en Eclipse que ni siquiera es gracioso.
nuzzolilo
@Nuzzolilo, esto es solo para depuración remota. Puede depurar localmente en eclipse sin todo eso.
Laplie Anderson
35

La solución alternativa que utilizo es simplemente usar System.in/System.out en lugar de Console cuando uso Eclipse. Por ejemplo, en lugar de:

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

Puedes usar:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line = bufferedReader.readLine();
Laplie Anderson
fuente
20
No creo que pueda leer las contraseñas con enmascaramiento de contraseñas de esa manera.
Sualeh Fatehi
3
... y uno necesita manejar IOException, que no se tira en caso de Console.readLine().
dma_k
5

La razón por la que esto ocurre es porque eclipse ejecuta su aplicación como un proceso en segundo plano y no como un proceso de nivel superior con una consola del sistema.

Heath Borders
fuente
5

Puede implementar una clase usted mismo. A continuación se muestra un ejemplo:

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
fuente
4

Encontré algo sobre esto en http://www.stupidjavatricks.com/?p=43 .

Y lamentablemente, dado que la consola es final, no puede extenderla para crear un contenedor alrededor de system.in y system.out que lo haga tampoco. Incluso dentro de la consola de eclipse todavía tienes acceso a ellos. Probablemente sea por eso que Eclipse aún no ha conectado esto a su consola ...

Entiendo por qué no querrías tener otra forma de obtener una consola que no sea System.console, sin setter, pero no entiendo por qué no querrías que alguien pueda anular la clase para hacer un consola simulada / de prueba ...

John Gardner
fuente
4

Otra opción es crear un método para resumir ambas opciones y "conmutar por error" al método System.in cuando Console no está disponible. El siguiente ejemplo es bastante básico: puede seguir el mismo proceso para resumir los otros métodos en Console (readPassword, format) según sea necesario. De esa manera, puede ejecutarlo felizmente en Eclipse y, cuando se implementa, obtiene las funciones de la consola (por ejemplo, ocultación de contraseñas).

    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;
    }
cubo binario
fuente
2

Por lo que puedo decir, no hay forma de obtener un objeto Console de Eclipse. Solo me aseguraría de que consola! = Null, luego JAR y ejecutarlo desde la línea de comandos.

perimosocordiae
fuente
1

Parece que no hay forma de obtener un objeto java.io.Console cuando se ejecuta una aplicación a través de Eclipse. No se abre una ventana de consola de línea de comandos con la aplicación, ya que se ejecuta como un proceso en segundo plano (¿en segundo plano para Eclipse?). Actualmente, no hay ningún complemento de Eclipse para manejar este problema, principalmente debido al hecho de que java.io.Console es una clase final.

Todo lo que realmente puede hacer es probar el objeto Console devuelto para ver si es nulo y continuar desde allí.

Ross
fuente
1

Este enlace ofrece alternativas al uso de System.console (). Una es usar un BufferedReader envuelto alrededor de System.in, el segundo es usar un escáner envuelto alrededor de System.in.

Ninguno de los dos es tan conciso como la consola, ¡pero ambos funcionan en eclipse sin tener que recurrir a tonterías de depuración!

Dave Richardson
fuente
0

Digamos que su espacio de trabajo de Eclipse es C: \ MyWorkspace, que creó su aplicación java dentro de un proyecto maven MyProject, y su clase principal de Java es com.mydomain.mypackage.MyClass.

En este caso, puede ejecutar su clase principal que usa System.console()en la línea de comando:

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

NB1: si no está en un proyecto maven, verifique la carpeta de salida en las propiedades del proyecto | Ruta de compilación de Java | Fuente. Puede que no sea "objetivo / clases"

NB2: si es un proyecto maven, pero su clase está en src / test / java, probablemente tendrá que usar "target \ test-classes" en lugar de "target \ classes"

Paulo Merson
fuente