- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我曾经以为
System.console() != null
是确定启动我的 Java 应用程序的 shell 是否为交互式的可靠方法。这让我可以使用 ANSI escape sequences在交互模式和纯 System.out
/System.err
每当程序的输出被重定向到文件或通过管道传输到其他进程的标准输入时,类似于 --color=auto
许多 GNU 实用程序的模式。
System.console()
行为在 Windows 中有所不同。当 JVM 从 cmd.exe
启动时,方法确实返回一个非null
值(这对我来说没用,因为cmd.exe
不理解转义序列),返回值是always null
当我从 < em>Cygwin -- xterm
、mintty
或 cygwin
(最后一个只是一个 cmd.exe
运行一个 bash
子进程)。
如何在不读取 shell 脚本中的 $-
并将命令行参数传递到我的 Java 程序的情况下,在 Java 中测试交互式 shell?从 Java 测试 PS1
环境变量不是一个选项,因为 Java 是从 shell 脚本启动的,所以父进程是一个非交互式 shell,并且 PS1
未设置.
最佳答案
有一个conversation Cygwin 的维护者 (Corinna Vinschen) 解释说 Cygwin 伪 TTY 看起来像 Microsoft Visual C 运行时库 (MSVCRT) 的管道。她还建议围绕识别 Cygwin 伪 TTY 的 isatty()
函数实现包装器。
这个想法是获取与给定文件描述符关联的管道名称。 NtQueryInformationFile
函数获取 FILE_NAME_INFORMATION
结构,其中 FileName
成员包含管道名称。如果管道名称与以下模式匹配,则很可能该命令以交互模式运行:
\cygwin-%16llx-pty%d-{to,from}-master
对话很老了,但是管道名称的格式还是一样的: "\\\\.\\pipe\\cygwin-" + "%S-" +
+ "pty%d-from-master"
,其中 "\\\\.\\pipe\\"
是命名管道的约定前缀(参见 CreateNamedPipe
)。
所以 Cygwin 部分已经被黑了。下一步是从 C 代码创建 Java 函数。
以下代码创建了 ttyjni.TestApp
类,其中包含通过 Java native 接口(interface) (JNI) 实现的 istty()
方法。该代码在 GNU/Linux (x86_64
) 和 Windows 7(64 位)上的 Cygwin 上进行了测试。代码可以很容易地移植到 Windows (cmd.exe
),甚至可以按原样运行。
必需的组件
x86_64-w64-mingw32-gcc
编译器的 Cygwin布局
├── Makefile
├── TestApp.c
├── test.sh
├── ttyjni
│ └── TestApp.java
└── ttyjni_TestApp.h
生成文件
# Input: $JAVA_HOME
FINAL_TARGETS := TestApp.class
ifeq ($(OS),Windows_NT)
CC=x86_64-w64-mingw32-gcc
FINAL_TARGETS += testapp.dll
else
CC=gcc
FINAL_TARGETS += libtestapp.so
endif
all: $(FINAL_TARGETS)
TestApp.class: ttyjni/TestApp.java
javac $<
testapp.dll: TestApp.c TestApp.class
$(CC) \
-Wl,--add-stdcall-alias \
-D__int64="long long" \
-D_isatty=isatty -D_fileno=fileno \
-I"$(JAVA_HOME)/include" \
-I"$(JAVA_HOME)/include/win32" \
-shared -o $@ $<
libtestapp.so: TestApp.c
$(CC) \
-I"$(JAVA_HOME)/include" \
-I"$(JAVA_HOME)/include/linux" \
-fPIC \
-o $@ -shared -Wl,-soname,testapp.so $< \
-z noexecstack
clean:
rm -f *.o $(FINAL_TARGETS) ttyjni/*.class
TestApp.c
#include <jni.h>
#include <stdio.h>
#include "ttyjni_TestApp.h"
#if defined __CYGWIN__ || defined __MINGW32__ || defined __MINGW64__
#include <io.h>
#include <errno.h>
#include <wchar.h>
#include <windows.h>
#include <winternl.h>
#include <unistd.h>
/* vvvvvvvvvv From http://cygwin.com/ml/cygwin/2012-11/txt00003.txt vvvvvvvv */
#ifndef __MINGW64_VERSION_MAJOR
/* MS winternl.h defines FILE_INFORMATION_CLASS, but with only a
different single member. */
enum FILE_INFORMATION_CLASSX
{
FileNameInformation = 9
};
typedef struct _FILE_NAME_INFORMATION
{
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
NTSTATUS (NTAPI *pNtQueryInformationFile) (HANDLE, PIO_STATUS_BLOCK, PVOID,
ULONG, FILE_INFORMATION_CLASSX);
#else
NTSTATUS (NTAPI *pNtQueryInformationFile) (HANDLE, PIO_STATUS_BLOCK, PVOID,
ULONG, FILE_INFORMATION_CLASS);
#endif
jint
testapp_isatty(jint fd)
{
HANDLE fh;
NTSTATUS status;
IO_STATUS_BLOCK io;
long buf[66]; /* NAME_MAX + 1 + sizeof ULONG */
PFILE_NAME_INFORMATION pfni = (PFILE_NAME_INFORMATION) buf;
PWCHAR cp;
/* First check using _isatty.
Note that this returns the wrong result for NUL, for instance!
Workaround is not to use _isatty at all, but rather GetFileType
plus object name checking. */
if (_isatty(fd))
return 1;
/* Now fetch the underlying HANDLE. */
fh = (HANDLE)_get_osfhandle(fd);
if (!fh || fh == INVALID_HANDLE_VALUE) {
errno = EBADF;
return 0;
}
/* Must be a pipe. */
if (GetFileType (fh) != FILE_TYPE_PIPE)
goto no_tty;
/* Calling the native NT function NtQueryInformationFile is required to
support pre-Vista systems. If that's of no concern, Vista introduced
the GetFileInformationByHandleEx call with the FileNameInfo info class,
which can be used instead. */
if (!pNtQueryInformationFile) {
pNtQueryInformationFile = (NTSTATUS (NTAPI *)(HANDLE, PIO_STATUS_BLOCK,
PVOID, ULONG, FILE_INFORMATION_CLASS))
GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationFile");
if (!pNtQueryInformationFile)
goto no_tty;
}
if (!NT_SUCCESS (pNtQueryInformationFile (fh, &io, pfni, sizeof buf,
FileNameInformation)))
goto no_tty;
/* The filename is not guaranteed to be NUL-terminated. */
pfni->FileName[pfni->FileNameLength / sizeof (WCHAR)] = L'\0';
/* Now check the name pattern. The filename of a Cygwin pseudo tty pipe
looks like this:
\cygwin-%16llx-pty%d-{to,from}-master
%16llx is the hash of the Cygwin installation, (to support multiple
parallel installations), %d id the pseudo tty number, "to" or "from"
differs the pipe direction. "from" is a stdin, "to" a stdout-like
pipe. */
cp = pfni->FileName;
if (!wcsncmp(cp, L"\\cygwin-", 8)
&& !wcsncmp (cp + 24, L"-pty", 4))
{
cp = wcschr(cp + 28, '-');
if (!cp)
goto no_tty;
if (!wcscmp (cp, L"-from-master") || !wcscmp (cp, L"-to-master"))
return 1;
}
no_tty:
errno = EINVAL;
return 0;
}
/* ^^^^^^^^^^ From http://cygwin.com/ml/cygwin/2012-11/txt00003.txt ^^^^^^^^ */
#elif _WIN32
#include <io.h>
static jint
testapp_isatty(jint fd)
{
return _isatty(fd);
}
#elif defined __linux__ || defined __sun || defined __FreeBSD__
#include <unistd.h>
static jint
testapp_isatty(jint fd)
{
return isatty(fd);
}
#else
#error Unsupported platform
#endif /* __CYGWIN__ */
JNIEXPORT jboolean JNICALL Java_ttyjni_TestApp_istty
(JNIEnv *env, jobject obj)
{
return testapp_isatty(fileno(stdin)) &&
testapp_isatty(fileno(stdout)) ?
JNI_TRUE : JNI_FALSE;
}
ttyjni_TestApp.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class ttyjni_TestApp */
#ifndef _Included_ttyjni_TestApp
#define _Included_ttyjni_TestApp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: ttyjni_TestApp
* Method: istty
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_ttyjni_TestApp_istty
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
ttyjni/TestApp.java
package ttyjni;
import java.io.Console;
import java.lang.reflect.Method;
class TestApp {
static {
System.loadLibrary("testapp");
}
private native boolean istty();
private static final String ISTTY_METHOD = "istty";
private static final String INTERACTIVE = "interactive";
private static final String NON_INTERACTIVE = "non-interactive";
protected static boolean isInteractive() {
try {
Method method = Console.class.getDeclaredMethod(ISTTY_METHOD);
method.setAccessible(true);
return (Boolean) method.invoke(Console.class);
} catch (Exception e) {
System.out.println(e.toString());
}
return false;
}
public static void main(String[] args) {
// Testing JNI
TestApp t = new TestApp();
boolean b = t.istty();
System.out.format("%s(jni)\n", b ?
"interactive" : "non-interactive");
// Testing pure Java
System.out.format("%s(console)\n", System.console() != null ?
INTERACTIVE : NON_INTERACTIVE);
System.out.format("%s(java)\n", isInteractive() ?
INTERACTIVE : NON_INTERACTIVE);
}
}
测试.sh
#!/bin/bash -
java -Djava.library.path="$(dirname "$0")" ttyjni.TestApp
编译
make
在 Linux 上测试
$ ./test.sh
interactive(jni)
interactive(console)
interactive(java)
$ ./test.sh > 1
ruslan@pavilion ~/tmp/java $ cat 1
non-interactive(jni)
non-interactive(console)
non-interactive(java)
在 Cygwin 上测试
$ ./test.sh
interactive(jni)
non-interactive(console)
non-interactive(java)
$ ./test.sh > 1
$ cat 1
non-interactive(jni)
non-interactive(console)
non-interactive(java)
关于java - 确定 Java 程序是否已从交互式 shell 启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39968033/
我正在使用 Selenium Web 驱动程序 3.0,并且想要从打开的两个对话框(一个在后台,第二个在前台)的 Activity 对话框中单击“确定”按钮。如何从 html 下面的父 div 单击前
actions: [ FlatButton( onPressed: () {
我有一个问题有点超出我的范围(我真的很高兴我是 Beta)涉及重复项(所以 GROUP BY, HAVING, COUNT),通过将解决方案保留在 SQLite 附带的标准函数中而变得更加复杂。我正在
使用DBI是否可以确定SELECT语句的已执行语句句柄是否返回任何行而不从中获取行? IE。就像是: use DBI; ... my $sth = $dbh->prepare("SELECT ..."
是否可以为“确定”和“关闭”按钮指定回调函数? 如果是JQuery Modal,则可以在初始化时使用按钮字典指定回调函数。 Semantic-ui模态是否提供类似的功能?按下确定后,我该如何寻求其他逻
我想阅读警报中的消息。 示例:如果警报显示“错误的电子邮件地址”。怎么读呢?意味着我想将该消息存储在字符串中。 如何在“警报”中单击“确定”...?? 如何使用 Selenium 来做到这一点? 最佳
我有一个删除按钮: 我试图首先查明是否已选择一个网站,如果已选择一个网站,我需要确定是否已选择一个或多个列表项,如果是,则继续删除这些项目。 我的 if 语句不断返回“您必须首先选择您的列表”,即使它
部分出于好奇——我们想知道在我们的应用程序中发生了什么——部分是因为我们需要在我们的代码中找到一些潜在的问题,我喜欢在我们的网络应用程序运行时跟踪一些一般值。这尤其包括某些对象图的分配内存。 我们的应
我将 SweetAlert 与 Symfony 结合使用,我希望用户在完成删除操作之前进行确认。 发生的情况是,当用户单击删除按钮时,SweetAlert 会弹出,然后立即消失,并且该项目被删除。 在
我们有一个应用程序可以生成不包括字母 O 的随机基数 35 [0-9A-Z]。我正在寻找一种解决方案来查找包含任何淫秽英语单词的代码,而无需搜索包含 10,000 个条目的列表每个生成的代码。每秒生成
这是我做的: #include #include int betweenArray(int a, int b){ int *arr,i,range; range = b - a +
我知道如何创建 警报和确认框,但我不知道如何做的是实际单击“确定”。我有一个弹出确认框的页面。 我想使用 Java Script 插件单击“确定”。基本上,我希望我的代码单击页面上的链接,然后在出现提
代码: swal('Your ORDER has been placed Successfully!!!'); window.location="index.php"; 甜蜜警报工
>>> import re >>> s = "These are the words in a sentence" >>> regex = re.compile('are|words') >>> [m
使用确定的理想散列函数给出随机期望线性时间算法两个数组 A[1..n] 和 B[1..n] 是否不相交,即 A 的元素是否也是 B 的元素。 谁能告诉我如何做到这一点,甚至如何开始考虑它? 最佳答案
我在计算机科学课上有这段代码: int input=15; while (input < n ) { input = input *3;} 这段代码有 log3(n/15) 次循环的上限。我们怎样才能
我有一个允许 2 位玩家玩 TicTacToe 的程序。在每个玩家移动之后,它应该在那个点显示棋盘并返回一个名为 Status 的枚举,显示玩家是否应该继续,如果玩家赢了,还是平局。但是,该算法要么返
给定一个 y 值数组,例如 [-3400, -1000, 500, 1200, 3790],我如何确定“好的”Y 轴标签并将它们放置在网格上? ^ ---(6,000)-|---
假设我有一个检查用户登录的 SQL 语句: SELECT * FROM users WHERE username='test@example.com', password='abc123', expi
teradata中有返回表中哪一列被定义为主索引的命令吗?我没有制作一些我正在处理的表,也没有尝试优化我对这些表的连接。谢谢! 最佳答案 有dbc.IndicesV,其中IndexNumber=1表示
我是一名优秀的程序员,十分优秀!