调用KeyTool,重定向System.out无效 [英] Calling KeyTool, redirecting System.out has no effect

查看:109
本文介绍了调用KeyTool,重定向System.out无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我们要使用JRE随附的bog-standard keytool实用程序.但是,我们没有费心寻找正确的路径和可执行文件扩展名,生成子进程并运行可执行文件的麻烦,而是总有一个绝妙的主意(记住,我们每个人都不像我们所有人一样愚蠢!")直接调用KeyTool的main().它是用Java代码实现的,并且也随JRE一起提供,并且包含GPL的标准类路径"异常,因此我们可以对其进行链接.

So we want to use the bog-standard keytool utility that ships with a JRE. But rather than going through the trouble of finding the correct path and executable extension, spawning a subprocess, and running the executable, we collectively had the bright idea ("remember, none of us is as dumb as all of us!") to just call KeyTool's main() directly. It's implemented in Java code and also shipped with the JRE, and contains the standard "classpath" exception to the GPL so we can link against it.

看一下KeyTool的源代码,甚至对这种事情做了一些规定:如果您直接在自己的Java程序中调用KeyTool.main(),则有类似之类的注释,然后[有帮助的提醒] "和顶级main()能够将异常传播给调用代码,而不仅仅是死于System.exit().能够构建相同的命令行参数数组并运行KeyTool.main(stuff)而不用搞乱平台差异似乎是一件非常Java风格的事情,对吧?

Looking at the KeyTool source, there's even some provision made for this sort of thing: there are comments like "if you're calling KeyTool.main() directly in your own Java program, then [helpful reminder]" and the top-level main() is capable of propagating exceptions to calling code instead of just dying with System.exit(). Being able to just build the same command-line argument array and run KeyTool.main(stuff) instead of having to mess with platform differences seems like a very Java-esque thing to do, right?

在实践中,奇怪的事情发生了,我们不知道为什么.

In practice, weird things happen and we don't know why.

我们要捕获运行KeyTool的任何输出,该输出以这样的方式开始:

We want to capture any output from running KeyTool, which starts off like this:

// jdk/src/share/classes/sun/security/tools/KeyTool.java, line 331:
public static void main(String[] args) throws Exception {
    KeyTool kt = new KeyTool();
    kt.run(args, System.out);
}

private void run(String[] args, PrintStream out) throws Exception {
    // real code here, sends to 'out'
}

KeyTool入口点不允许我们传递PrintStream,它被硬编码为使用System.out.多亏了System.setOut,这应该可以.我们有一个OutputStream子类,该子类提供给JTextComponent,但对于初始编码,重定向到文本文件就可以了.这样我们的代码就可以了

The KeyTool entry points don't allow us to pass a PrintStream, it's hardcoded to use System.out. That should be okay thanks to System.setOut. We have an OutputStream subclass which feeds to a JTextComponent, but for initial coding, redirecting to a text file is fine. So our code does

PrintStream orig = System.out;
try {
    System.out.println("This is the last visible console line");
    System.setOut(new PrintStream("redirect_test.txt"));
    System.out.println("This is now redirected!");
    KeyTool.main(keytool_argv);  // "-help" and "-debug" for now
}
catch all the myriad ways things might go wrong { ... }
finally {
    System.setOut(orig);
    System.out.println("Back to normal console output");
}

但是,当我们运行代码时,redirect_test.txt文件仅包含现在已重定向!". keytool的"-help"输出以及在前后的println调用仍会显示在控制台上.

But when we run the code, the redirect_test.txt file contains only "This is now redirected!". The output from keytool's "-help" still shows up on the console, along with the before-and-after println calls.

直接调用KeyTool时还有其他奇怪之处,例如在Java 7和Java 8之间更改了包和类名,但这很容易通过反射进行处理. (Java 8中KeyTool源代码中的注释仍然引用Java 7名称,呵呵.)唯一奇怪的是,它的"System.out"如何不受其他地方使用的相同重定向的影响. (不,没有奇怪的import语句带来特殊的System替换.)

There are some other oddities in calling KeyTool directly, like the package and class name has changed between Java 7 and Java 8, but that's easy to deal with via reflection. (The comments in the KeyTool source in Java 8 still refer to the Java 7 name, heh.) The only thing just freaky weird is how its "System.out" is strangely not affected by the same redirection that works everywhere else. (No, there are no weird import statements bringing in a special System replacement.)

这是 Java 7的KeyTool.java的在线副本如果您碰巧没有遇到OpenJDK.

Here's an online copy of Java 7's KeyTool.java if you don't happen to have OpenJDK sitting around.

推荐答案

您只需要重定向System.outSystem.err,因为用法说明会打印到标准错误流而不是标准输出流.试试这个:

You just need to redirect both System.out and System.err, since the usage instructions get printed to the standard error stream instead of the standard output stream. Try this:

PrintStream original = System.out;
PrintStream redirected = new PrintStream("redirect_test.txt")
try {
    System.out.println("This is the last visible console line");
    System.setOut(redirected);
    System.setErr(redirected);
    System.out.println("This is now redirected!");
    KeyTool.main(keytool_argv);  // "-help" and "-debug" for now
}
catch all the myriad ways things might go wrong { ... }
finally {
    System.setOut(original);
    System.setErr(original);
    System.out.println("Back to normal console output");
}

这篇关于调用KeyTool,重定向System.out无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆