Могу ли я найти ширину консоли с помощью Java?
Есть ли способ найти ширину консоли, на которой запущена моя программа Java?
Я хотел бы, чтобы это было кросс-платформой, если это возможно...
У меня нет желания изменять ширину буфера или окна, я просто хочу узнать его ширину, чтобы я мог правильно форматировать текст, который печатается на экране.
Ответы
Ответ 1
К этой проблеме не существует надежных кросс-платформенных решений. Действительно, бывают ситуации, когда невозможно узнать, какова реальная ширина консоли.
Например, в системе Linux вы обычно можете узнать условные размеры терминала из переменных окружения LINES и COLUMNS. Хотя эти переменные автоматически обновляются при изменении размеров окон "эмулятора терминала", это не всегда так. В самом деле, в случае удаленной консоли, подключенной по протоколу telnet, нет способа получить фактические размеры терминала в пользовательской оболочке.
EDIT. Просто добавьте, что если пользователь изменит размеры своего xterm в Linux после запуска приложения Java, приложение Java не будет уведомлено, и оно не увидит новые измерения отражены в его копии переменных среды LINES и COLUMNS!
РЕДАКТИРОВАТЬ 2. Моя ошибка: они являются переменными оболочки bash
, но по умолчанию не экспортируются в среду. Вы можете "исправить" это, запустив export COLUMNS LINES
, прежде чем запускать приложение Java.
Ответ 2
На самом деле, Java-библиотека уже существует для этого в Java: JLine 2. (Там есть старая версия на SourceForce, но эта ссылка на GitHub кажется последней).
Это работало для меня под Linux (Mint 14) и Windows (я не знаю, какую версию), используя JLine 2.11:
terminalWidth = jline.TerminalFactory.get().getWidth();
JLine обещает работать и на Mac.
Я обнаружил, что он возвращает плохую ширину (например, 1
!) В консоли Eclipse (но даже родной Java-консоль не работает под Eclipse!) И, к сожалению, под Cygwin. Но я работал над этим с кодом, который проверяет необоснованные значения (< 10
) и просто использует 80 в этих случаях.
Обновление для JLine 3 (за Марк -Спасибо, приятель!):
terminalWidth = org.jline.terminal.TerminalBuilder.terminal().getWidth()
Ответ 3
Изменить: см. комментарий @dave_thompson_085 о ProcessBuilder
, поскольку это почти наверняка лучший подход.
Еще один ответ, упомянутый под управлением tput cols
в script, прежде чем вы начнете свою команду. Но если вы хотите запустить это после того, как Java уже запущена, используя Runtime.getRuntime().exec()
, вы обнаружите, что tput не может разговаривать с вашим терминалом, потому что Java перенаправляет stdout и stderr. В качестве обходного пути, не используемого для всех, вы можете использовать магическое устройство /dev/tty
, которое относится к терминалу текущего процесса. Это позволяет вам запускать что-то вроде этого:
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
Это работает для меня в Linux, но я бы не ожидал, что он будет работать повсюду. Он, надеюсь, будет работать на Mac. Это определенно не будет работать в Windows, хотя это может быть с Cygwin.
Ответ 4
Java 6 имеет класс java.io.Console, но, к сожалению, у него нет требуемых функций. Получение ширины окна консоли невозможно в стандартной библиотеке Java и чистой межплатформенной Java.
Вот альтернатива Java console library, которая позволяет вам получить размер экрана, но включает в себя DLL для Windows. Возможно, вы сможете взять исходный код и скомпилировать часть C в общую библиотеку Linux или Mac OS X, чтобы она также работала на этих платформах.
Ответ 5
Я уже работал над этой проблемой. Я использую несколько разных методов. Однако сложно иметь по-настоящему кросс-платформенное решение.
Я попытался сделать что-то вроде этого:
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");
Вы можете читать/тестировать и добавлять "экспорт COLUMNS" в файл .bashrc в каждом домашнем каталоге пользователей Linux с помощью метода String.contains( "export COLUMNS" ) и свойства user.dir.
Это позволит вам загружать столбцы при каждом запуске приложения java.
Затем я передам его временному файлу. Вот так:
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 what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
Другой вариант, который у вас есть, - выполнить yor Java.jar с bash script при запуске. Внутри script вы можете использовать "tput cols" для получения ширины. Затем передайте это значение вашему Java-приложению как String [] arg.
Так же:
//#!/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
почему эта сложная задача с Java? Очевидно, хорошее место для написания хорошего API. Думаю, мы могли бы попробовать Apache.commons.exec?
Ответ 6
У Python есть хорошее решение: 11.9.3. Запрос размера выходного терминала. Я бы не задерживал дыхание, ожидая, что это будет доступно в базовой Java, но вы могли бы использовать Jython, чтобы сделать Python доступная функциональность.
Ответ 7
Для меня единственный способ получить представление о окне терминала (все еще неверно, когда изменяется размер окна) - использовать команду типа
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "mode con");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
При запуске без части cmd.exe
он показывает, что команда не найдена. Также обратите внимание на часть redirectError
. Если не используется, тогда будет использоваться размер вывода Java, а не фактический. Только с этой комбинацией можно было захватить фактический размер.