Java プログラムの入出力ストリームが端末に接続されているかどうかを確認するにはどうすればよいですか?
質問
Java プログラムに、用途に応じて異なるデフォルト設定 (冗長性、サポートされている場合は色付きの出力) を持たせたいと考えています。C には、ファイル記述子が端末に接続されている場合は 1 を返し、そうでない場合は 0 を返す isatty() 関数があります。Java にはこれに相当するものはありますか?JavaDoc には、InputStream または PrintStream に関するものは何もありません。
解決
System.console()は、アプリケーションが接続されている場合はアプリケーションが接続されているコンソールを返し、そうでない場合は null
を返します。 (これはJDK 6以降でのみ利用可能です。)
他のヒント
System.console() と isatty()
System.console() は、@Bombe によってすでに述べられているように、コンソールの接続をチェックする単純なユースケースで機能します。ただし、System.console() の問題は、コンソールに接続されているのが STDIN か STDOUT (あるいはその両方、またはどちらでもない) を判断できないことです。
Javaとの違い System.console() そして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) 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 の対象 OS の一部がサポートしていないのではないかと思います。
JNI を使用して isatty() を呼び出す
技術的には は (stephen-c@ が指摘したように) Java でこれを行うことは可能です。 かなり単純な JNI, ただし、アプリケーションが C コードに依存することになり、他のシステムに移植できない可能性があります。そこに行きたくない人もいるのは理解できます。
JNI がどのようになるかを示す簡単な例 (詳細を詳しく説明します):
ジャバ: tty/TtyUtils.java
public class TtyUtils {
static {
System.loadLibrary("ttyutils");
}
// FileDescriptor 0 for STDIN, 1 for STDOUT
public native static boolean isTty(int fileDescriptor);
}
子: 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++ を除けば) 私にとって最初に思い浮かぶのは次のとおりです。 ルビー, パイソン, ゴラン そして パール.
簡単な答えは、標準Javaには 'isatty'に直接相当するものはないということです。 Java Bug Databaseには、このようなものに対する RFE があります。 1997年。ただし、 だけが 1 投票しました。
理論的には、JNIマジックを使用して「isatty」を実装できる場合があります。しかし、それはあらゆる種類の潜在的な問題をもたらします。私はこれを自分でやろうとも思いません...
1-Javaのバグ修正の投票は、OracleがSunを引き継いだ頃になくなりました。
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) );