Как я могу проверить, подключены ли потоки ввода / вывода Java-программы к терминалу?
Вопрос
Я бы хотел, чтобы программа Java имела разные настройки по умолчанию (детализация, возможно, цветной вывод, если поддерживается) в зависимости от ее использования.В C есть функция isatty(), которая вернет 1, если файловый дескриптор подключен к терминалу, и 0 в противном случае.Есть ли эквивалент для этого в Java?Я ничего не видел в JavaDoc для InputStream или PrintStream.
Решение
System.console () возвращает консоль, к которой подключено ваше приложение, если оно подключено, в противном случае возвращается null
. (Обратите внимание, что он доступен только с JDK 6 и выше.)
Другие советы
System.console () vs isatty ()
System.console (), как уже упоминалось @Bombe, работает для простых случаев использования проверки подключения к консоли. Однако проблема с System.console () заключается в том, что он не позволяет определить, подключен ли к консоли STDIN или STDOUT (или оба, или ни один).
Разница между System.console () в Java. и isatty () C может проиллюстрировать следующую разбивку по регистру (где мы передаем данные в / из гипотетического класса 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) STDINTTY
%> 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 и
Краткий ответ: в стандартной Java нет прямого эквивалента 'isatty'. Существует RFE для чего-то подобного в базе данных ошибок Java, поскольку 1997, но только у Теоретически вы можете реализовать isatty, используя магию JNI. Но это вводит все виды потенциальных проблем. Я бы даже не подумал сделать это сам ... 1 - Голосование за исправление ошибок Java ушло в то время, когда Oracle захватил Sun. было 1 одного жалкого голоса.
Вы можете использовать библиотеку jnr-posix для вызова собственных методов posix из Java:
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import java.io.FileDescriptor;
POSIX posix = POSIXFactory.getPOSIX();
posix.isatty(FileDescriptor.out);
Если вы не хотите самостоятельно компилировать исходный код 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) );