有没有一种方法确定 Java System.in 是否“交互式”?

5
如果输入是交互式的,即来自控制台,我想要打印一个命令提示符,例如“>”。
但如果它被重定向,例如来自文件,则不希望提示。
System.in是一个抽象InputStream,似乎没有任何方法可以实现这一点。
也许你可以使用instanceof判断具体类型是否不同?
另外,如果System.out被重定向到文件,我也不想提示。

针对Linux的特定解决方案,可以使用JNI,请参见此处。您只需要将fileno(stderr)更改为fileno(stdin)即可。 - Brad Mace
1
可能是重复的问题:如何检查Java程序的输入/输出流是否连接到终端? - Kristian Holdhus
2个回答

5
据我所知,纯Java中没有办法做到这一点,即使在JNI / JNA中实现也会很复杂。另一个选择可能是使用JDK 1.6中引入的新Console API。这允许您尝试获取控制台的读取器/写入器。如果成功,结果保证是交互式的...就像您所需的那样。
第二个选择是在用于启动应用程序的包装脚本中执行“检查交互性”,并通过系统属性将信息传递给Java。例如,在GNU / Linux系统上,可以使用tty(1)命令告诉stdin是否连接到“tty”设备。
请注意,还有其他方法来处理需要在非交互式运行时避免不必要提示的要求:
如果System.out被重定向到文件,则也不想提示。(我认为您可能意思是System.in被重定向。这是以非交互方式运行通常从用户处接收交互式输入的应用程序的正常方式...)
其他替代方案包括:
您可以修改程序将提示写入(例如)System.err,并将其重定向到其他位置。
您可以修改程序以具有“不提示”或“从文件接受输入”的选项。

1
应该可以工作。如果没有连接控制台,System.console() 会返回 null。 http://java.sun.com/javase/6/docs/api/java/io/Console.html - Andrew McKinlay
1
控制台 API 在某种意义上是有效的,但如果用户想要从文件中获取应用程序的输入,则打开新的控制台流会破坏其功能。在我看来,只有当应用程序无法从非交互式 stdin 中读取数据时,才应使用控制台 API,否则可能会带来危险。 - Stephen C
我并没有考虑打开一个新的控制台流。我只是在想,你可以检查System.console()的非空返回值来确定是否连接到了控制台。 - Andrew McKinlay
1
@Andrew - 但这有什么帮助吗?它并没有告诉你System.in/out是否连接到控制台。 - Stephen C
是的,你说得对,我没有考虑到。它只告诉你Java是否从控制台启动,但显然stdin/out仍然可以被重定向。 - Andrew McKinlay

0
自Java 6以来,有一个名为java.lang.System.console()的方法:

虚拟机是否拥有控制台取决于底层平台以及虚拟机被调用的方式。如果虚拟机从交互式命令行启动而没有重定向标准输入和输出流,则其控制台将存在并且通常连接到从中启动虚拟机的键盘和显示器。如果虚拟机自动启动,例如由后台作业调度器,则通常不会有控制台。

如果此虚拟机具有控制台,则它由该类的唯一实例表示,可以通过调用java.lang.System.console()方法获取。如果没有可用的控制台设备,则该方法的调用将返回null。


请参阅有关System.console()的先前讨论。 - Andrew McKinlay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接