¿Puedo encontrar el ancho de la consola con Java?


¿Hay alguna forma de encontrar el ancho de la consola en la que se está ejecutando mi programa Java?

Me gustaría que esto sea multiplataforma si es posible...

No tengo ningún deseo de cambiar el ancho del búfer o la ventana, solo quiero saber su ancho para poder formatear correctamente el texto que se está imprimiendo en la pantalla.

Author: masher, 2009-08-17

7 answers

No hay soluciones multiplataforma fiables para este problema. De hecho, hay situaciones en las que no es posible saber cuál es el ancho real de la consola.

Por ejemplo, en un sistema Linux normalmente puede encontrar las dimensiones teóricas de la terminal a partir de las variables de entorno LÍNEAS y COLUMNAS. Si bien estas variables se actualizan automáticamente cuando cambia el tamaño de algunas ventanas de "emulador de terminal", este no siempre es el caso. De hecho, en el caso de una consola remota conectado a través del protocolo telnet, no hay forma de obtener las dimensiones reales del terminal al shell del usuario.

EDIT: Solo para agregar que si el usuario cambia las dimensiones de su xterm en Linux después de lanzar una aplicación Java, la aplicación Java no será notificada, y no verá las nuevas dimensiones reflejadas en su copia de las variables de entorno LINES and COLUMNS!

EDITAR 2 : Mi error, son variables de shell bash, pero no se exportan al entorno por predeterminado. Puede "arreglar" esto ejecutando export COLUMNS LINES antes de ejecutar su aplicación Java.

 24
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-29 00:28:58

En realidad, ya existe una biblioteca Java para hacer esto en Java: JLine 2. (Hay una versión antigua en SourceForce, pero ese enlace a GitHub parece ser el último.)

Esto funcionó para mí bajo Linux (Mint 14) y Windows (no se que versión), usando JLine 2.11:

terminalWidth = jline.TerminalFactory.get().getWidth();

JLine promete trabajar en Mac, también.

He encontrado que devuelve malos anchos(como 1!) bajo la consola Eclipse (pero incluso la consola nativa de Java no funciona bajo Eclipse!), y, desafortunadamente, bajo Cygwin. Pero he trabajado alrededor de esto con código que comprueba valores irrazonables (< 10) y solo usa 80 en esos casos.

Actualización para JLine 3 (por Mark - gracias, amigo!):

terminalWidth = org.jline.terminal.TerminalBuilder.terminal().getWidth()
 16
Author: Michael Scheper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-08 23:46:29

Editar: Ver el comentario de @dave_thompson_085 sobre ProcessBuilder, ya que es casi seguro que es un mejor enfoque.

Otra respuesta mencionó ejecutar tput cols en un script antes de iniciar el comando. Pero si desea ejecutar esto después de que Java ya se haya iniciado, utilizando Runtime.getRuntime().exec(), encontrará que tput no puede hablar con su terminal, porque Java ha redirigido stdout y stderr. Como solución no portátil, puede usar el dispositivo mágico /dev/tty, que se refiere al terminal del proceso actual. Eso te permite ejecutar algo como esto:

Process p = Runtime.getRuntime().exec(new String[] {
    "bash", "-c", "tput cols 2> /dev/tty" });
// Read the output of this process to get your terminal width

Esto funciona para mí en Linux, pero no esperaría que funcionara en todas partes. Con suerte funcionará en Mac. Definitivamente no funcionará en Windows, aunque podría hacerlo con Cygwin.

 8
Author: Jack O'Connor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-11 21:28:36

Java 6 tiene una clase java.io.Console, pero desafortunadamente carece de la funcionalidad que está pidiendo. Obtener el ancho de la ventana de la consola no es posible con la biblioteca Java estándar y Java puro multiplataforma.

Aquí hay una alternativa Java console library que le permite obtener el tamaño de la pantalla, pero incluye una DLL específica de Windows. Es posible que pueda tomar el código fuente y compilar la parte C en una biblioteca compartida de Linux o Mac OS X, para que funcione esas plataformas también.

 4
Author: Jesper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-17 07:22:38

He estado trabajando en este problema antes. Utilizo un par de técnicas diferentes. Sin embargo, es difícil tener una solución verdaderamente multiplataforma.

Intenté hacer algo como esto:

String os = System.getProperty("os.name").toLowerCase();

    //Windows
    if(os.contains("win")){
        System.out.append("Windows Detected");
        //set Windows Dos Terminal width 80, height 25
        Process p = Runtime.getRuntime().exec("mode 80, 25");
    }
    //Mac
    if(os.contains("mac")){
        System.out.println("Macintosh Detected");
        //... I dont know...try Google
    }
    //Linux
    if(os.contains("linux")){
        System.out.println("Linux Detected");

Puede leer / probar y añadir "exportar COLUMNAS" a la .archivo bashrc en todos los directorios personales de los usuarios de Linux con la cadena.contiene el método ("exportar COLUMNAS") y el usuario.propiedad dir.

Eso le permitiría obtener las columnas para cargar cada vez que se inicie la aplicación java hasta.

Entonces lo pasaría a un archivo temporal. Así:

try {
    ProcessBuilder pb = new ProcessBuilder("bash","-c","echo $COLUMNS >/home/$USER/bin/temp.txt" );  
        pb.start();

    }catch (Exception e) {
        System.out.println("exception happened - here's what I know: ");
        e.printStackTrace();
        System.exit(-1);
    }
}

Otra opción que tienes es ejecutar yor Java.jar con un script bash al inicio. Dentro del script puedes usar "tput cols" para obtener el ancho. Luego pase ese valor a su aplicación Java como una cadena [] arg.

Así:

//#!/bin/bash

//#clear the screen

clear 

//#get the console width and height

c=$[$(tput cols)]

l=$[$(tput lines)]

//#pass the columns, lines and an optional third value as String[] args.

java -jar ~/bin/Plus.jar $c $l $1

¿Por qué es esta una tarea tan difícil con Java? Obviamente un buen lugar para escribir una buena API. Supongo que podríamos probar con Apache.común.exec así?

 2
Author: aubreybourke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-19 22:17:24

Python parece tener una buena solución: 11.9.3. Consultar el tamaño del terminal de salida . No aguantaría la respiración esperando que esto esté disponible en core Java, pero es posible que pueda usar Jython para hacer que la funcionalidad de Python esté disponible.

 0
Author: Michael Scheper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-22 01:26:00

Para mí, la única manera de tener una idea de la ventana de terminal (todavía no es correcta cuando la ventana cambia de tamaño) es usar un comando como

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "mode con");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);

Cuando se ejecuta sin la parte cmd.exe, muestra que el comando no se pudo encontrar. Observe también la parte redirectError. Si no se utiliza, entonces se utilizará el tamaño de salida de Java, no el real. Solo con esta combinación era posible agarrar el tamaño real.

 0
Author: Panayotis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 21:01:39