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

Как проверить, подключены ли потоки ввода/вывода программы Java к терминалу?

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

4b9b3361

Ответ 1

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

Ответ 2

System.console() vs isatty()

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

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

1) STDIN и STDOUT являются tty

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

2) STDOUT - tty

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

3) STDIN - tty

%> 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/С++), Ruby, Python, Голанг и Perl.

Ответ 3

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

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


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

Ответ 4

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

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

POSIX posix = POSIXFactory.getPOSIX();

posix.isatty(FileDescriptor.out);