提问者:小点点

在java控制台中打印一行(与“\n”相反)


我在其他语言中看到了一些与此相关的问题,并对此做了相当多的研究。首先,在我们开始进入兔子洞之前,我必须描述一下我为什么要这样做。我正在打印一棵二叉树,我找到了一种我认为其他人都找不到的方法(在我搜索过的网络上找不到)。它解决了许多和间距和冲突有关的问题,我可能会在后面回答打印前的Btree问题。无论如何,执行上述操作的一个基本部分是能够将换行符(光标)向上移动一行。我也会满足于移动车厢返回一行。

我已经对底部附近名为“编辑1-3”的问题进行了三次编辑。

我的特定Windows版本(可能相关):Windows 10 v1607操作系统版本:14393.2035

问题是这很容易用ANSI转义字符完成

ANSI转义码:https://en.wikipedia.org/wiki/ANSI_escape_code

\033[A是我想要实现的特定代码(从一个关于在python中向上移动一行的问题中得到的)。

所以问题解决了,对吗?哦,不,甚至不接近。问题是,显然windows有一个“很棒”的更新,它可能破坏了所有与ANSI/控制台相关的东西。下面链接到一个关于这一点的问题,但有不同的ANSI要求,但根本问题是相同的。

如何使用系统在控制台中打印颜色。出来普林顿?

tl:dr它不适用于windows,因为某些原因,你需要一个大的库来完成这项工作或其他工作。

所以我试着对更新本身做了一些深入的研究,为什么这恰好是特定于windows的(当然),我被引导到了这一点。

windows问题的根本原因:https://github.com/Microsoft/WSL/issues/1173

tl;dr:基本上,更新更改了cmd的默认设置。exe,这是java使用的默认控制台。改变的是如何为“子应用程序”即java(使用控制台但不是控制台本身的东西)处理ANSI代码的控制台设置。更新之前的默认设置是,子应用程序继承了控制台的默认设置,即启用ANSI。现在(因为很明显,以前的默认设置破坏了一切),他们更改了它,这样子应用程序就不会从控制台继承默认设置。这意味着,如果java希望启用ANSI,java必须有效地自行设置此控制台模式。java命令显然有太多的库可以实现这一点,但在可用的好库中,存在一些问题。首先,他们需要maven,我不想要maven,我也不喜欢需要一百万个额外的库来做一些非常简单的事情,这增加了我的代码所依赖的东西的数量(这很糟糕)。因此,我试图避免使用简单的解决方案,如“只使用JANSI”来setConsoleModefor ANSI。

在我完成阅读/理解后,我试图进入我的注册表编辑器,并试图更改控制台(cmd.exe)的默认设置,以始终启用ANSI,即使是子应用程序(又名java)。这是在GitHub讨论中提出的,但令我惊讶的是,具体的设置甚至不适合我。(它应该在计算机中-

由于我无法编辑控制台设置,如果没有我不想要的东西的大型库,我尝试跳出框框思考,我在java设置中乱了阵脚。我发现了java设置控制台的确切位置,并发现我可以更改该设置以在java中使用不同的控制台。我最近安装了git,并且知道GitBash是可用的,所以我尝试使用下面的问题(以及google)作为起点。

https://superuser.com/questions/1196463/start-sh-exe-bash-with-given-path

我无法让这该死的东西工作。它没有返回任何错误,也没有做任何新的操作。它甚至是为“当前项目”设置的,所以当我运行我的项目时,它应该做一些不同的事情。不是吗?我认为部分问题在于我的根git文件夹有问题(不在程序文件中)。这可能是因为我正在使用的计算机是一台工作计算机,可能那里的某些设置会影响git的安装位置,我不知道,但我知道的是,当我更换控制台时,我尝试了以下路径:

C:\Users\abbotts1\AppData\Local\Programs\Git\bin\bash。exe

我也尝试过:

C:\用户\abbots1\AppData\本地\程序\Git\bash.exe

C:\用户\abbots1\AppData\本地\程序\Git\bin\sh.exe

“C:\Users\abbotts1\AppData\Local\Programs\Git\bin\sh.exe”--登录-i

每次更换控制台后,我都会尝试以下代码:

public class ExpressionEvaluator {

    public static void main(String[] args) {
        System.out.println("1");
        System.out.println("\033[A");
        System.out.println("2");
    }
}

我总是得到:

1.

额外的线在这里

2个

作为输出。如果我删除移动光标向上ANSI println语句尝试我得到:

1.

2个

我想要的是:

2个

1.

(关键是,我可以自由地向上移动一条线)

我也试着让他们打印声明,但也没用。

这就是我想要的,一个类似这样的答案:

>

或者是一个非侵入性的库,它不需要maven和一百万其他东西来启用ANSI,这样我就可以在控制台中用java运行ANSI并获得所需的输出

或者是一个编程解决方案,它允许我在没有整个ANSI的情况下有效地打印一行

或者帮助配置IntelliJ控制台,以便我可以实际使用不同的控制台并使用ANSI打印一行

因为1和4是超级用户问题,2是“我需要一个图书馆”,我在这里更多地讨论第3点。如果这个问题没有解决办法,而答案是一个离题的问题,请告诉我没有解决办法。我不知道该怎么问这个问题,因为这是一个“特定于编程的问题”,它只是有许多解决方案,其中一些不在“主题”上,因为它们不是编程解决方案。如果唯一的答案是“解决方案不在主题上”,那么我会去适当的地方询问。当我去其他地方问这个问题时,请告诉我是否应该删除这个问题。

因为3是在这里讨论的主题,我将讨论我的想法:

也许我可以做一些系统来只打印某些数组,而不是上下移动行(即有一个数组来表示行,遍历树,而不是上下移动行,只是切换要打印的数组)。我不认为这是非常有效的,它有点浪费数组和处理能力,但如果这是一个解决方案,我愿意听到它。这就是我能“想到的”,但我所做的大部分努力都是试图让ANSI发挥作用。

用多离题解/解问题问这些问题,合适的方式是什么?干脆不问他们是不是更好?涉及问题的解决方案是否构成变色龙问题?我不想给自己带来元效应。

我又一次尝试了git bash的整个过程,男孩,这是一个过程。终端中的实际git bash路径需要在后面加上--login-I参数。前任:

C:\git\bin\sh.exe--login-i

此设置适用于java终端。然后你必须设置一个名为PATH的windows环境变量到你的java JDK。转到你的路径环境变量(有一百万个youtube视频),并为你的JDK设置一个名为PATH的新变量。Ex:

C:\ProgramFiles\Java\jdk-10.0。1\bin

这个问题:

如何让gitbash找到javac命令?

都经历了这个过程

Tl;为了让GitBash能够识别javac和java命令,您必须设置一个windows路径变量。

一旦完成,你需要像在任何终端一样运行你的java和javac命令。顺便说一句,要小心,因为git bash中的路径需要两个'\'符号,而不是普通的'\',所以你的源目录路径可能看起来像这样:

C:\IdeaProjects\Calculator\src\

然后你就跑:

ClassName.java

Java类

但是它实际上并不打印ANSI输出,而是打印原始转义字符。此外,我发现我使用了错误的转义序列(我有错误的数字来表示'esc'按钮,因为'esc'键表示为一些数字,但我有错误的十六进制数字,我使用像x330或其他东西)。我还了解到符号是这样的:

'esc键十六进制数'[''参数十六进制值,用逗号分隔'

所以这可能看起来像:

\x1B[A

实际的字母和数字是十六进制值(没有明显的0x...),第一个转义十六进制值有一个x(为什么?)。不管怎样,当在Java中运行它们时,你需要转义转义字符(对吗?)例如,代码可能看起来像:

System.out.println("\\\x1B [A");

我刚刚注意到堆栈溢出也会漏掉这些,所以我实际上有三个“\”,但对你们来说,它只显示两个“\”,奇怪吧?不管怎样,回到我刚才说的

但是,输出仍然不起作用!这就是我所处的位置。我已经完成了上述操作,99.9%的人知道git bash安装正确并且运行良好,但当我运行此操作时:

public class ExpressionEvaluator {
    public static void main(String[] args) {
        System.out.println("1");
        System.out.println("\\x1B [A");
        System.out.println("2");
    }
}

我在java控制台(不是git bash??)中得到了这一点:

1.

\x1B[A

2个

在git bash中:

1.

\x1B[A

2个

我真正想要的是:

2个

1.

因为ANSI转义字符应该将光标/换行符/任何东西向上移动一行。如果我运行上述代码,但使用ANSI代码“\x1B[F”,则会发生同样的情况。只输出原始ANSI。我非常确定git bash应该是“本机ANSI感知的”,我在网站上看到有人这么说,所以我不知道为什么它不起作用。

我仍然不知道这是两个独立的控制台输出还是同一个控制台输出。我真的说不出来,所以如果有人想留下评论说‘是的,是同一个傻瓜’,我会很感激,因为我在网上找不到确切的消息来源。我认为这只是IntelliJ中的控制台设置表明了这一点。

我听说有一个术语变量需要在windows上设置或操作。我已经检查了自己它在使用什么:

Echo$TERM

在git bash,我回来了:

西格温

所以我不知道这到底是好是坏,因为我已经浏览了你能想到的所有搜索词,它们都会导致“git bash Color not working”(git bash Color not working)(git bash colors not working)(git bash colors not working)(git bash colors not working)(git bash colors not working)(git bash colors not working)(git bash colors not working)(git working)(git bash colors not working)(git)或其他一些不需要的语言)Java和使用其他非IntelliJ的IDE。有些页面确实有我的特定要求,它们说了一些关于术语应该是xterm或其他东西,比如xterm-256或用于“颜色”输出的东西,类似这样的东西。我对这些东西太不熟悉了,所以我甚至不知道从哪里开始。

我需要知道为什么git bash打印原始ANSI而不是实际使用ANSI。

我所知道的

我将git bash与IntelliJ一起使用,99.9%确定我的路径设置正确,我能够从git bash运行java类,我将它设置为IntelliJ终端,并且我当前将windows TERM变量设置为cygwin。

我不知道的是

我不知道应该是什么术语,也无法在web上找到它,我无法判断当我单击绿色箭头“run”时出现的IntelliJ控制台是否与git bash控制台相同,我也无法确定是否有其他原因阻止我实际解释ANSI。

我需要什么

我需要一个简单的解释,直接从r/ELI5中解释git bash有什么问题,以及如何修复它。如果不能简单地解释,或者没有什么问题,那么我可能会尝试另一个所谓的“本机ANSI感知”终端。我认为Powershell是列出的另一个选项。我的最佳选择是术语变量必须是其他的东西,或者git bash从一开始就不是真正具有ANSI意识和能力的。我见过其他关于颜色的问题,但它们的修复是针对旧版本/不同语言和其他东西的,或者它们实际上不起作用。我还没有找到一个好的“git bash输出IntelliJ中的原始ANSI”页面,我已经使用了几个小时了。我所能得到的只是GitHub关于与此相关的“bug”的长时间讨论,它们让我感到困惑,不会带来解决方案,可能是活跃的,或者只是不包含任何解决方案。

在做了更多的研究之后,我知道我以前的转义码是正确的:

\033[A]

\x1B[A

应该是相似的。

我还了解到,我使用的不是控制台,而是Windows本身。我现在知道了这一点,因为我已经尝试编译并运行cmd。exe、gitbash和powershell。要更改前面提到的默认设置(控制台不支持子应用程序的ansi),您必须通过程序本身显式启用它,而不是依赖于控制台或其他东西。

链接到一个用Python解释这一点的问题:

如何在Windows 10控制台中使用对ANSI转义序列的新支持?

tl;博士

他们使用的方法称为getConsoleModesetConsoleModeVIRTUALTERMINALPROCESSING标志。显然,您需要使用这些来实际设置控制台模式以支持ANSI。我目前不知道这些是java中隐藏在某处的东西,还是(可能)需要添加到基本java库中的东西。我将试着找出他们是如何从这个问题中得到ctypes的(似乎是他们为了起诉这些方法而导入的东西),并得到我需要的方法。一旦我这样做了,我会把它作为一个答案贴出来,除非你们中的一个在我之前弄明白了,并且能更好地解释它。

显然,如果您仅从控制台使用转义序列,那么转义序列可以正常工作,但是如果您使用“子应用程序”,那么转义序列就不工作。因此,至少我们现在肯定知道问题的根本原因。

发现这一点非常相关,尤其是控制台虚拟终端序列部分(左侧导航栏):

https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

这在底部附近有一个完整的C语言实现,说明了如何使控制台能够读取ANSI。显然,这根本不需要库,但实际更改控制台默认值以使用这样的代码的过程需要系统管理员权限、熟悉程序文件以及大量其他内容(至少在windows 10更新之前更改颜色支持时是这样)。现在默认情况下它仍然处于禁用状态,但可以启用。我还不知道如何直接从控制台尝试ANSI。我试过多次

echo\x1B[(在此处插入ANSI代码)

但是这些命令在任何终端(cmd、gitbash、powershell)中似乎都不起作用。他们只是返回原始代码

\x1B[(不管ANSI代码是什么)

很明显,我对控制台是新手,所以可能使用了错误的命令,如果是的话,请随时告诉我,但是我看到的示例使用了echo。不管怎么说,我认为直接从终端调用ANSI应该是可行的,因为默认情况下它应该是启用的,而不是子应用程序(windows 10更新后),但可能不是,可能在默认情况下禁用了它,即使启用了它,也仍然会禁用子应用程序(Java),除非在所述子应用程序(Java)中显式更改。我将尝试看看是否可以直接从控制台启用ANSI,或者链接的C代码是否需要直接移植到Java或在控制台中运行才能正常工作。问题是我不知道如何获取C代码使用的导入/包含,并将其用于java代码。我宁愿不只是接受用C编写的“解决方案”,并尝试将其与java代码一起使用,我宁愿翻译、更好地理解它,并拥有自己的代码来做同样的事情。

我被告知的另一个选项是ANSICON,它类似于某种插件,您可以在控制台中安装带有-I标志的插件,至少应该在控制台中启用ANSI。我找到了这个

https://community.liferay.com/blogs/-/blogs/enable-ansi-colors-in-windows-command-prompt

上面更详细地解释了这个过程。

我的特定windows版本和版本更新

我学到的另一件事是Windows 10的特定版本,改变ANSI控制台行为的更新就像Windows 10 v1151或其他东西,我会尝试找到直接源此网页,但我目前有Windows 10 v1607,所以我想我应该要乖。其中包括实际的操作系统构建,我有14393.2035,我认为这在我之前的一个链接中被确定为这个过程的一个特别中间的更新(我相信它是关于更新的整个GitHub讨论的一个,你可以找到它这里:https://github.com/Microsoft/WSL/issues/1173)。我有一台工作电脑,所以我不能真正进行系统更新,因为我不是管理员,我怀疑信息技术会让实习生到处更新工作电脑。

无论如何,我将继续尝试,看看是否可以将C代码转换为java,我将测试它,然后尝试发布一个答案。如果你在我前面,请告诉我。


共1个答案

匿名用户

在“编辑2”中引用python的方式(https://stackoverflow.com/a/36760881/309816)只需调用特定于Windows的本机代码(内核32,不可移植)即可“修复”此问题。

我想你对此没意见,并且想在Java中做同样的事情(即当你检测到Windows时调用kernel32)...

在Java中实现同样功能的一个非常轻量级的库是JNA,它为kernel32提供了现成的包装器(请参阅:https://java-native-access.github.io/jna/4.2.1/com/sun/jna/platform/win32/Kernel32.html)

你似乎在追求这种方法:https://java-native-access.github.io/jna/4.2.1/com/sun/jna/platform/win32/Wincon.html#SetConsoleMode-com.sun.jna.platform.win32.WinNT.HANDLE-int-

希望这对你有用。

编辑:从技术上讲,您只需要jna。jar(请参见此处的入门:https://github.com/java-native-access/jna/blob/master/www/GettingStarted.md),但我建议您也使用jna平台。jar,这样您就不需要自己编写在运行时为kernel32生成映射的代码。

JNA之家:https://github.com/java-native-access/jna

我认为添加1个(如果添加jna平台,则添加2个)具有非常特定作用域的JAR(在没有所有JNI准备开销的情况下执行本机调用)是足够轻量级的。您不需要生成任何头,也不需要在编译过程中更改任何内容。只需将这些JAR添加到类路径即可。

您还应该在问题中澄清这是关于Windows的。也许可以将标题编辑为:“在Windows上的java控制台(与“\n”相反)中打印一行”,因为这实际上是关于您希望用java解决的特定于平台的问题。