Posso encontrar a largura do console com o Java?

Existe uma maneira de encontrar a largura do console em que meu programa Java está sendo executado?

Eu gostaria que isso fosse uma plataforma cruzada, se possível …

Eu não tenho desejo de alterar a largura do buffer ou a janela, eu só quero saber sua largura para que eu possa formatar corretamente o texto que está sendo impresso na canvas.

Não há soluções confiáveis de plataforma cruzada para esse problema. Na verdade, há situações em que não é possível saber qual é a largura real do console.

Por exemplo, em um sistema Linux, você normalmente pode descobrir as dimensões do terminal imaginário das variables ​​de ambiente LINES e COLUMNS. Embora essas variables ​​sejam atualizadas automaticamente quando você redimensiona algumas janelas “emulador de terminal”, isso nem sempre é o caso. De fato, no caso de um console remoto conectado via protocolo telnet, não há como obter as dimensões reais do terminal para o shell do usuário.

EDIT : Apenas para adicionar que, se o usuário altera as dimensões de seu / xterm no Linux após o lançamento de um aplicativo Java, o aplicativo Java não será notificado, e não verá as novas dimensões refletidas em sua cópia das linhas e variables ​​de ambiente COLUMNS!

EDIT 2 : Meu erro, eles são variables ​​de shell bash , mas não são exportados para o ambiente por padrão. Você pode “consertar” isso executando export COLUMNS LINES antes de executar seu aplicativo Java.

Na verdade, uma biblioteca Java já existe para fazer isso em Java: JLine 2 . (Há uma versão antiga no SourceForce, mas esse link para o GitHub parece ser o mais recente.)

Isso funcionou para mim no Linux (Mint 14) e no Windows (não sei qual versão), usando o JLine 2.11:

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

JLine promete trabalhar no Mac também.

Descobri que ele retorna larguras ruins (como 1 !) Sob o console do Eclipse (mas até mesmo o console nativo do Java não funciona sob o Eclipse!) E, infelizmente, sob o Cygwin. Mas eu trabalhei em torno disso com código que verifica valores não razoáveis ​​( < 10 ) e apenas usa 80 nesses casos.

Atualização para o JLine 3 (por Mark - obrigado, mate!):

 terminalWidth = org.jline.terminal.TerminalBuilder.terminal().getWidth() 

Edit: Veja o comentário do @ dave_thompson_085 sobre o ProcessBuilder , já que é quase certamente uma abordagem melhor.

Outra resposta mencionou a execução de tput cols em um script antes de iniciar seu comando. Mas se você quiser executar isso depois que o Java já tiver iniciado, usando Runtime.getRuntime().exec() , você verá que tput não pode falar com seu terminal, porque o Java redirecionou stdout e stderr. Como uma solução não portátil, você pode usar o /dev/tty mágico, que se refere ao terminal do processo atual. Isso permite que você execute algo assim:

 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 

Isso funciona para mim no Linux, mas eu não esperaria que funcionasse em todos os lugares. Espero que funcione no Mac. Definitivamente não funcionará no Windows, embora isso possa acontecer com o Cygwin.

O Java 6 tem uma class java.io.Console, mas infelizmente não possui a funcionalidade que você está solicitando. Não é possível obter a largura da janela do console com a biblioteca Java padrão e o Java puro e de plataforma cruzada.

Aqui está uma biblioteca de console Java alternativa que permite obter o tamanho da canvas, mas inclui uma DLL específica do Windows. Você pode pegar o código-fonte e compilar a parte C em uma biblioteca compartilhada Linux ou Mac OS X, para que ele funcione também nessas plataformas.

Eu tenho trabalhado neste problema antes. Eu uso algumas técnicas diferentes. No entanto, é difícil ter uma solução verdadeiramente de plataforma cruzada.

Eu tentei fazer algo assim:

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

Você pode ler / testar e append “export COLUMNS” ao arquivo .bashrc em todos os diretórios home de usuários Linux com o método String.contains (“export COLUMNS”) e a propriedade user.dir.

Isso permitiria que as colunas fossem carregadas toda vez que o aplicativo java fosse iniciado.

Então eu passaria para um arquivo temporário. Como isso:

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

Outra opção é executar yor Java.jar com um script bash na boot. Dentro do script você pode usar “tput cols” para obter a largura. Em seguida, passe esse valor para seu aplicativo Java como um String [] arg.

Igual a:

 //#!/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 que isso é uma tarefa tão difícil com Java? Obviamente, um bom lugar para escrever uma boa API. Eu acho que nós poderíamos tentar o Apache.commons.exec também?

O Python parece ter uma boa solução: 11.9.3. Consultando o tamanho do terminal de saída . Eu não prenderei a respiração esperando que isso esteja disponível no Java principal, mas você pode usar o Jython para disponibilizar a funcionalidade do Python.

Para mim, a única maneira de ter uma idéia da janela do terminal (ainda não correta quando a janela é redimensionada) é usar um comando como

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

Quando executado sem a parte cmd.exe , isso mostra que o comando não foi encontrado. Observe também a parte redirectError . Se não for usado, o tamanho da saída Java será usado, não o real. Somente com essa combinação foi possível pegar o tamanho real.