Eclipse IDE对java.io.Console的支持

107

我使用Eclipse集成开发环境来开发、编译和运行我的Java项目。今天,我正在尝试使用java.io.Console类来管理输出,更重要的是,用户输入。

问题在于,当应用程序“通过”Eclipse运行时,System.console()返回null。Eclipse在后台进程上运行程序,而不是在我们熟悉的带有控制台窗口的顶层进程上运行。

有没有办法强制Eclipse将程序作为顶级进程运行,或者至少创建一个JVM可以识别的控制台?否则,我只能将项目打包成jar文件,在Eclipse外部的命令行环境中运行。


另请参阅 https://dev59.com/O18d5IYBdhLWcg3wxUfC#26473083。我确定 System.outSystem.in 对于我的用例已足够,并放弃使用 System.console() - OneWorld
我将项目导出为可运行的jar文件,但仍然收到控制台空指针错误。 - Abhigyan
10个回答

49

我假设您想要能够在Eclipse中使用逐步调试。您可以通过将已构建的类设置在bin目录中,并将其添加到JRE类路径中来在外部运行这些类。

java -cp workspace\p1\bin;workspace\p2\bin foo.Main

您可以使用远程调试器进行调试,并利用项目中构建的类文件。

在此示例中,Eclipse 项目结构如下所示:

workspace\project\
                 \.classpath
                 \.project
                 \debug.bat
                 \bin\Main.class
                 \src\Main.java

1. 启动JVM控制台调试模式

debug.bat 是一个Windows批处理文件,应该在cmd.exe控制台外部运行。

@ECHO OFF
SET A_PORT=8787
SET A_DBG=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=%A_PORT%,server=y,suspend=y
java.exe %A_DBG% -cp .\bin Main
在参数中,debug端口已被设置为8787。suspend=y参数告诉JVM等待调试器连接。
2. 创建Debug Launch Configuration
在Eclipse中打开Debug对话框(Run > Open Debug Dialog...),并创建一个新的Remote Java Application配置,以下是配置:
- 项目:您的项目名称 - 连接类型:标准(Socket Attach) - 主机名:localhost - 端口号:8787
3. 调试
因此,您要调试应用程序时所需执行的操作只有:
- 设置断点 - 在控制台中启动批处理文件 - 启动调试配置
您可以在bug 122429中跟踪此问题。您可以通过使用此处描述的抽象层在应用程序中解决此问题。

1
我还会在批处理文件的末尾加上一个pause,这样在它关闭之前你就可以看到任何闪现的错误消息了。 - Matt Lyons-Wood
12
对我来说,这是最后一根稻草。如果我必须要做这么多才能进行调试,我会转回Netbeans。Eclipse中存在太多未修复的错误和UI烦恼问题,甚至都不好笑了。 - marknuzz
@Nuzzolilo,这只是为了远程调试。你可以在Eclipse本地进行调试,而无需那么麻烦。 - Laplie Anderson

33
我使用的解决方法是在使用Eclipse时,直接使用System.in/System.out而不是Console。例如,改为:
String line = System.console().readLine();

你可以使用:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line = bufferedReader.readLine();

21
我认为你无法通过密码遮掩的方式读取密码。 - Sualeh Fatehi
3
需要处理IOException,但在Console.readLine()方法中不会抛出该异常。 - dma_k

5

这种情况发生的原因是因为Eclipse将您的应用程序作为后台进程运行,而不是作为带有系统控制台的顶级进程。


4

http://www.stupidjavatricks.com/?p=43上找到一些相关信息。

可悲的是,由于控制台是final的,因此您不能扩展它以创建包装器,包装system.in和system.out的内容。 即使在eclipse控制台中,您仍然可以访问它们。 这可能是为什么eclipse尚未将其插入其控制台的原因...

我理解为什么您不希望除System.console之外还有其他获取控制台的方式,没有setter,但我不明白为什么您不希望允许某人重写该类以创建模拟/测试控制台...


4
你可以自己实现一个类。以下是一个示例:
public class Console {
    BufferedReader br;
    PrintStream ps;

    public Console(){
        br = new BufferedReader(new InputStreamReader(System.in));
        ps = System.out;
    }

    public String readLine(String out){
        ps.format(out);
        try{
            return br.readLine();
        }catch(IOException e)
        {
            return null;
        }
    }
    public PrintStream format(String format, Object...objects){
        return ps.format(format, objects);
    }
}

4
另一种选择是创建一个方法来包装这两个选项,并在Console不可用时“故障转移”到System.in方法。下面的示例是相当基本的 - 您可以按照相同的过程包装Console中的其他方法(readPassword,format)以满足要求。这样,您就可以在Eclipse中愉快地运行它,并在部署时使用控制台功能(例如密码隐藏)。
    private static String readLine(String prompt) {
        String line = null;
        Console c = System.console();
        if (c != null) {
             line = c.readLine(prompt);
        } else {
            System.out.print(prompt);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            try {
                 line = bufferedReader.readLine();
            } catch (IOException e) { 
                //Ignore    
            }
        }
        return line;
    }

2
据我所知,无法从Eclipse获取控制台对象。只需确保console!= null,然后将其打包成JAR文件并从命令行运行即可。

1

链接 提供了使用 System.console() 的替代方案。其中一个方法是使用包装在 System.in 周围的 BufferedReader,另一个方法是使用包装在 System.in 周围的 Scanner。

这两种方法都不像控制台那样简洁,但无需通过调试达到相同效果,就可以在 Eclipse 中正常工作!


1

在通过Eclipse运行应用程序时,似乎没有办法获取java.io.Console对象。由于它作为后台进程(Eclipse的后台)运行,因此不会打开命令行控制台窗口。目前,没有Eclipse插件来处理此问题,主要是因为java.io.Console是一个final类。

你真正能做的就是测试返回的Console对象是否为空,并从那里继续。


0
假设您的Eclipse工作区是C:\ MyWorkspace, 您在Maven项目MyProject中创建了Java应用程序, 并且您的Java主类是com.mydomain.mypackage.MyClass。
在这种情况下,您可以在命令行上运行使用System.console()的主类:
java -cp C:\MyWorkspace\MyProject\target\classes com.mydomain.mypackage.MyClass

注意1:如果不是Maven项目,请在项目属性|Java构建路径|源中检查输出文件夹。它可能不是“target/classes”。
注意2:如果是Maven项目,但您的类位于src/test/java中,则可能需要使用“target\test-classes”而不是“target\classes”。

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