Подтвердить что ты не робот

Могу ли я найти ширину консоли с помощью Java?

Есть ли способ найти ширину консоли, на которой запущена моя программа Java?

Я хотел бы, чтобы это было кросс-платформой, если это возможно...

У меня нет желания изменять ширину буфера или окна, я просто хочу узнать его ширину, чтобы я мог правильно форматировать текст, который печатается на экране.

4b9b3361

Ответ 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, а не фактический. Только с этой комбинацией можно было захватить фактический размер.