Как я могу проверить, подключены ли потоки ввода / вывода Java-программы к терминалу? - PullRequest
35 голосов
/ 10 сентября 2009

Я бы хотел, чтобы программа на Java имела разные настройки по умолчанию (многословность, возможно цветной вывод, если поддерживается) в зависимости от ее использования. В C есть функция isatty (), которая будет возвращать 1, если дескриптор файла подключен к терминалу, и 0 в противном случае. Есть ли эквивалент для этого в Java? Я не видел ничего в JavaDoc для InputStream или PrintStream.

Ответы [ 5 ]

33 голосов
/ 02 мая 2014

System.console () против isatty ()

System.console (), как уже упоминалось @Bombe, работает для простых случаев использования проверки подключения к консоли. Однако проблема с System.console () заключается в том, что он не позволяет определить, подключен ли к консоли STDIN или STDOUT (или оба, или ни один).

Различие между Java System.console () и C isatty () может быть проиллюстрировано в следующей разбивке по регистру (когда мы передаем данные в / из гипотетического Foo. класс):

1) STDIN и STDOUT tty

%> java Foo
System.console() => <Console instance>
isatty(STDIN_FILENO) => 1
isatty(STDOUT_FILENO) => 1

2) STDOUT является

%> echo foo | java Foo
System.console() => null
isatty(STDIN_FILENO) => 0
isatty(STDOUT_FILENO) => 1

3) Стандарт

%> java Foo | cat
System.console() => null
isatty(STDIN_FILENO) => 1
isatty(STDOUT_FILENO) => 0

4) Ни STDIN, ни STDOUT не являются tty

%> echo foo | java Foo | cat
System.console() => null
isatty(STDIN_FILENO) => 0
isatty(STDOUT_FILENO) => 0

Я не могу сказать вам, почему Java не поддерживает лучшую проверку tty. Интересно, не поддерживаются ли некоторые целевые ОС Java.

Использование JNI для вызова isatty ()

Технически возможно сделать это в Java (как указал stephen-c @) с некоторым довольно простым JNI , но это сделает ваше приложение зависимым от C-кода это не может быть переносимым на другие системы. Я понимаю, что некоторые люди могут не захотеть туда идти.

Краткий пример того, как будет выглядеть JNI (с большим количеством деталей):

Java: tty / TtyUtils.java

public class TtyUtils {
    static {
        System.loadLibrary("ttyutils");
    }
    // FileDescriptor 0 for STDIN, 1 for STDOUT
    public native static boolean isTty(int fileDescriptor);
}

C: ttyutils.c (предполагает совпадение ttyutils.h ), скомпилированный в libttyutils.so

#include <jni.h>
#include <unistd.h>

JNIEXPORT jboolean JNICALL Java_tty_TtyUtils_isTty
          (JNIEnv *env, jclass cls, jint fileDescriptor) {
    return isatty(fileDescriptor)? JNI_TRUE: JNI_FALSE;
}

Другие языки:

Если у вас есть возможность использовать другой язык, я думаю, что большинство других языков поддерживают проверку tty. Но, поскольку вы задали вопрос, вы, вероятно, уже знаете это. Первое, что приходит мне на ум (кроме C / C ++): Ruby , Python , Golang и Perl .

25 голосов
/ 10 сентября 2009

System.console () возвращает консоль, к которой подключено ваше приложение, если оно подключено, в противном случае возвращается null. (Обратите внимание, что он доступен только с JDK 6).

8 голосов
/ 10 сентября 2009

Краткий ответ: в стандартной Java нет прямого эквивалента 'isatty'. С 1997 года существует RFE для чего-то подобного в базе данных ошибок Java, но только у было было 1 один жалкий голос.

Теоретически вы можете реализовать isatty, используя магию JNI. Но это вводит все виды потенциальных проблем. Я бы даже не подумал сделать это сам ...


1 - Голосование за исправление ошибок Java ушло в то время, когда Oracle захватил Sun.

6 голосов
/ 03 апреля 2015

Вы можете использовать библиотеку jnr-posix для вызова собственных методов posix из Java:

import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import java.io.FileDescriptor;

POSIX posix = POSIXFactory.getPOSIX();

posix.isatty(FileDescriptor.out);
2 голосов
/ 27 сентября 2018

Если вы не хотите самостоятельно компилировать исходный код на C, вы можете использовать библиотеку Jansi. Это намного меньше, чем jnr-posix

<dependency>
  <groupId>org.fusesource.jansi</groupId>
  <artifactId>jansi</artifactId>
  <version>1.17.1</version>
</dependency>

...

import static org.fusesource.jansi.internal.CLibrary.isatty;

...

System.out.println( isatty(STDIN_FILENO) );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...