Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if a Java program's input/output streams are connected to a terminal?

I would like a Java program to have different default settings (verbosity, possibly colored output where supported) depending on its use. In C, there is an isatty() function which will return 1 if a file descriptor is connected to a terminal, and 0 otherwise. Is there an equivalent for this in Java? I haven't seen anything in the JavaDoc for InputStream or PrintStream.

like image 698
Zilk Avatar asked Sep 10 '09 07:09

Zilk


People also ask

Which java class is used to read information from an input output stream?

The Java I/O package, a.k.a. java.io, provides a set of input streams and a set of output streams used to read and write data to files or other input and output sources.

What are input and output streams in java?

In Java, streams are the sequence of data that are read from the source and written to the destination. An input stream is used to read data from the source. And, an output stream is used to write data to the destination. class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"

Which stream is used for input in java?

Java Byte streams are used to perform input and output of 8-bit bytes, whereas Java Character streams are used to perform input and output for 16-bit unicode. Though there are many classes related to character streams but the most frequently used classes are, FileReader and FileWriter.


2 Answers

System.console() vs isatty()

System.console(), as already mentioned by @Bombe, works for simple use cases of checking console-connectedness. The problem with System.console() however, is that it doesn't let you determine whether it's STDIN or STDOUT (or both or neither) that is connected to a console.

The difference between Java's System.console() and C's isatty() can be illustrated in the following case-breakdown (where we pipe data to/from a hypothetical Foo.class):

1) STDIN and STDOUT are tty

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

2) STDOUT is tty

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

3) STDIN is tty

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

4) Neither STDIN nor STDOUT are tty

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

I can't tell you why Java doesn't support better tty-checking. I wonder if some of Java's target OS's don't support it.

Using JNI to call isatty()

It technically is possible to do this in Java (as stephen-c@ pointed out) with some fairly simple JNI, but it will make your application dependent on C-code that may not be portable to other systems. I can understand that some people may not want to go there.

A quick example of what the JNI would look like (glossing over a lot of details):

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 (assumes matching ttyutils.h), compiled to 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; } 

Other languages:

If you have the option of using another language, most other languages I can think of support tty-checking. But, since you asked the question, you probably already know that. The first that come to mind for me (aside from C/C++) are Ruby, Python, Golang and Perl.

like image 56
Kristian Holdhus Avatar answered Oct 04 '22 00:10

Kristian Holdhus


System.console() will return the console your application is connected to if it is connected, otherwise it returns null. (Note that it’s only available from JDK 6 on.)

like image 37
Bombe Avatar answered Oct 04 '22 02:10

Bombe