我可以用Java找到控制台宽度吗?
有没有办法找到运行Java程序的控制台的宽度 我希望这是跨平台的,如果可能的话我可以用Java找到控制台宽度吗?,java,console,Java,Console,有没有办法找到运行Java程序的控制台的宽度 我希望这是跨平台的,如果可能的话 我不想更改缓冲区或窗口的宽度,我只想知道它的宽度,这样我就可以正确格式化正在打印到屏幕上的文本。Java6有一个类Java.io.Console,但不幸的是它缺少您所要求的功能。使用标准Java库和纯跨平台Java无法获得控制台窗口宽度 这里有一个替代方案,允许您获取屏幕大小,但它包括一个Windows特定的DLL。您可能能够获取源代码并将C部分编译到Linux或Mac OS X共享库中,这样它也可以在这些平台上工作
我不想更改缓冲区或窗口的宽度,我只想知道它的宽度,这样我就可以正确格式化正在打印到屏幕上的文本。Java6有一个类Java.io.Console,但不幸的是它缺少您所要求的功能。使用标准Java库和纯跨平台Java无法获得控制台窗口宽度
这里有一个替代方案,允许您获取屏幕大小,但它包括一个Windows特定的DLL。您可能能够获取源代码并将C部分编译到Linux或Mac OS X共享库中,这样它也可以在这些平台上工作。对于这个问题没有可靠的跨平台解决方案。事实上,在某些情况下,不可能知道真正的控制台宽度是多少 例如,在Linux系统上,您通常可以从LINES和COLUMNS环境变量中找到概念上的终端维度。当您调整某些“终端仿真器”窗口的大小时,这些变量会自动更新,但情况并非总是如此。事实上,对于通过telnet协议连接的远程控制台,无法获得用户外壳的实际终端尺寸 编辑:只需补充一点,如果用户在启动Java应用程序后在Linux上更改他/她的xterm的维度,Java应用程序将不会收到通知,并且不会在其
行
和列
环境变量的副本中看到新维度
编辑2:我的错误:
行
和列
是bash
shell变量,默认情况下它们不会导出到环境中。在运行Java应用程序之前,可以通过运行导出列行来“修复”这个问题。我以前一直在解决这个问题。我使用了几种不同的技术。然而,很难有一个真正的跨平台解决方案
我试过这样做:
String os = System.getProperty("os.name").toLowerCase();
//Windows
if(os.contains("win")){
System.out.append("Windows Detected");
//set Windows Dos Terminal width 80, height 25
Process p = Runtime.getRuntime().exec("mode 80, 25");
}
//Mac
if(os.contains("mac")){
System.out.println("Macintosh Detected");
//... I dont know...try Google
}
//Linux
if(os.contains("linux")){
System.out.println("Linux Detected");
Process p = Runtime.getRuntime().exec(new String[] {
"bash", "-c", "tput cols 2> /dev/tty" });
// Read the output of this process to get your terminal width
您可以使用String.contains(“export COLUMNS”)方法和user.dir属性读取/测试并将“export COLUMNS”附加到每个Linux用户主目录中的.bashrc文件中
这将允许您在每次java应用程序启动时加载列
然后我会将其传递到临时文件。像这样:
try {
ProcessBuilder pb = new ProcessBuilder("bash","-c","echo $COLUMNS >/home/$USER/bin/temp.txt" );
pb.start();
}catch (Exception e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
另一个选择是在启动时使用bash脚本执行yor Java.jar。在脚本中,您可以使用“tput cols”获取宽度。然后将该值作为字符串[]arg传递给Java应用程序
像这样:
//#!/bin/bash
//#clear the screen
clear
//#get the console width and height
c=$[$(tput cols)]
l=$[$(tput lines)]
//#pass the columns, lines and an optional third value as String[] args.
java -jar ~/bin/Plus.jar $c $l $1
为什么这对Java来说是一项如此困难的任务?显然,这是一个编写好API的好地方。我想我们也可以试试Apache.commons.exec?编辑:请参阅@dave_thompson_085对
ProcessBuilder
的评论,因为这几乎肯定是一种更好的方法
另一个答案提到在启动命令之前在脚本中运行tput cols
。但是如果您想在Java已经启动之后运行它,使用Runtime.getRuntime().exec()
,您会发现tput无法与您的终端通信,因为Java已经重定向了stdout和stderr。作为一种完全不可移植的解决方法,您可以使用神奇的/dev/tty
设备,它指的是当前进程的终端。这样,您就可以运行以下内容:
String os = System.getProperty("os.name").toLowerCase();
//Windows
if(os.contains("win")){
System.out.append("Windows Detected");
//set Windows Dos Terminal width 80, height 25
Process p = Runtime.getRuntime().exec("mode 80, 25");
}
//Mac
if(os.contains("mac")){
System.out.println("Macintosh Detected");
//... I dont know...try Google
}
//Linux
if(os.contains("linux")){
System.out.println("Linux Detected");
Process p = Runtime.getRuntime().exec(new String[] {
"bash", "-c", "tput cols 2> /dev/tty" });
// Read the output of this process to get your terminal width
这对我来说在Linux上是可行的,但我不希望它在任何地方都能奏效。它有望在Mac上工作。它肯定不会在Windows上工作,尽管它可能与Cygwin一起工作。Python似乎有一个很好的解决方案:。我不会屏住呼吸等待它在核心Java中可用,但您可能可以使用它使Python功能可用。实际上,Java中已经存在一个Java库来实现这一点:。(SourceForce上有一个旧版本,但到GitHub的链接似乎是最新的。) 在Linux(Mint 14)和Windows(我不知道是什么版本)下,使用JLine 2.11,这对我来说是有效的:
terminalWidth = jline.TerminalFactory.get().getWidth();
JLine承诺也会在Mac上工作
我发现它在Eclipse控制台下返回错误的宽度(比如1
!)(但即使是Java的本机控制台在Eclipse下也不能工作!),不幸的是,在Cygwin下。但我已经用代码解决了这个问题,这些代码检查不合理的值(<10
),在这些情况下只使用80
JLine 3的更新(谢谢,伙计!):
对我来说,了解终端窗口(当窗口调整大小时仍然不正确)的唯一方法是使用如下命令
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "mode con");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
如果在没有
cmd.exe
部分的情况下运行,则表明找不到该命令。还要注意重定向错误
部分。如果不使用,则将使用Java输出大小,而不是实际大小。只有通过这种组合,才有可能获得实际的尺寸。有一个技巧,您可以根据需要使用。它们不提供查询控制台大小的直接方法,但它们确实有一个请求当前光标位置的命令。通过将光标移动到非常高的行和列,然后请求光标位置,可以获得准确的测量值
将其与存储/恢复光标位置的命令相结合,如以下示例所示:
将以下序列发送到终端(stdout)
现在看一下stdin,您应该会收到一个类似于\u001b[25;80R”
的序列,其中25是行数,80是列数
我第一次在图书馆看到这个
更新:
我知道有四种不同的方法可以实现这一点,但它们都对程序运行的环境或与之对话的终端设备/仿真器做出了某些假设
- 使用VT100协议。这是w