¿Puedo encontrar el ancho de la consola con Java?

¿Hay alguna manera de encontrar el ancho de la consola en la que se ejecuta mi progtwig Java?

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

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

No hay soluciones confiables multiplataforma 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 averiguar las dimensiones del terminal nocional 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 es siempre el caso. De hecho, en el caso de una consola remota conectada mediante protocolo telnet, no hay forma de obtener las dimensiones reales del terminal en el shell del usuario.

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

EDIT 2 : Mi error, son variables de shell bash , pero no se exportan al entorno de forma predeterminada. Puede “arreglarlo” ejecutando export COLUMNS LINES antes de ejecutar su aplicación Java.

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

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

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

JLine también promete trabajar en Mac.

Descubrí que devuelve anchos incorrectos (¡como 1 !) Debajo de la consola de Eclipse (¡pero incluso la consola nativa de Java no funciona con Eclipse!) Y, por desgracia, bajo Cygwin. Pero he solucionado esto con un código que verifica 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() 

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

Otra respuesta mencionó la ejecución de tput cols en una secuencia de comandos antes de iniciar el comando. Pero si quiere ejecutar eso después de que Java ya haya comenzado, usando Runtime.getRuntime().exec() , encontrará que la entrada no puede comunicarse con su terminal, porque Java ha redirigido stdout y stderr. Como solución temporal no portátil, puede utilizar el dispositivo mágico /dev/tty , que hace referencia 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 espero que funcione en todas partes. Esperemos que funcione en Mac. Definitivamente no funcionará en Windows, aunque podría funcionar con Cygwin.

Java 6 tiene una clase java.io.Console, pero lamentablemente carece de la funcionalidad que está solicitando. No es posible obtener el ancho de la ventana de la consola con la biblioteca Java estándar y Java pura y multiplataforma.

Aquí hay una biblioteca alternativa de consola de Java 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 comstackr la parte C en una biblioteca compartida Linux o Mac OS X, para que funcione también en esas plataformas.

He estado trabajando en este problema antes. Utilizo un par de técnicas diferentes. Sin embargo, es difícil tener una verdadera solución 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 agregar “export COLUMNS” al archivo .bashrc en cada directorio de inicio de los usuarios de Linux con el método String.contains (“export COLUMNS”) y la propiedad user.dir.

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

Entonces lo pasaría a un archivo temporal. Me gusta esto:

 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 tiene es ejecutar yor Java.jar con un script bash al inicio. Dentro del script puede usar “tput cols” para obtener el ancho. Luego pase ese valor a su aplicación Java como String [] arg.

Al igual que:

 //#!/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 es un buen lugar para escribir una buena API. ¿Supongo que podríamos probar Apache.commons.exec también?

Python parece tener una buena solución: 11.9.3. Consultando el tamaño de la terminal de salida . No aguante 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.

Para mí, la única manera de tener una idea de la ventana del terminal (aún 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. También tenga en cuenta la parte redirectError . Si no se usa, se usará el tamaño de salida de Java, no el tamaño real. Solo con esta combinación fue posible tomar el tamaño real.