是否可以在JAVA中编写正确且可移植的控制台输出“ hello world”?

时间:2019-03-04 12:40:33

标签: java runtime-error portability system.out correctness

我是JAVA的新手,无法找到一种编写“ hello world”应用程序的方法,该应用程序在所有平台上都无需进行任何更改就可以正常工作,并且可以检测并处理输出错误。

特别是,我想将以下可移植的C程序移植到JAVA:

“ Makefile”:

.POSIX:

TARGETS = hello

.PHONY: all clean

all: $(TARGETS)

clean:
    -rm $(TARGETS)

“ hello.c”:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
   if (puts("Hello, world!") >= 0 && fflush(0) == 0) return EXIT_SUCCESS;
   (void)fputs("An output error occurred.\n", stderr);
   return EXIT_FAILURE;
}

该程序旨在像这样工作:

$ make
c99 -O    hello.c   -o hello

$ ./hello
Hello, world!

$ ./hello > /dev/full
An output error occurred.

不幸的是,我还无法在JAVA中实现同样的功能。

System.out.println()和System.out.flush()似乎都没有检查I / O错误,或者也许我只是无法捕获它们。

我已经尝试捕获IOException类型的异常,但是编译器告诉我

error: exception IOException is never thrown in body of corresponding try statement

所以这显然不是正确的方法。

但是,即使我找到捕获输出错误的方法,我仍然不知道该移植哪种退出代码,因为JAVA似乎没有定义与C的EXIT_FAILURE相对应的内容。

考虑到JAVA一直被誉为高度可移植的应用程序开发系统,我很难相信。

如果即使是简单的“ hello world”的正确,可移植的实现方式已经超过了“一次编写,随处运行”平台的功能,那将是非常令人震惊的事情。

因此,请帮助我创建行为与C版本完全相同且仍可移植的JAVA实现。

多亏了khelwood和其他人,我设法创建了迄今为止效果最好的以下JAVA实现:

public class HelloWorld {
   private static class OutputError extends java.io.IOException { }

   private static void println(String s) throws OutputError {
      System.out.println(s);
      if (System.out.checkError()) throw new OutputError();
   }

   private static void flush() throws OutputError {
      System.out.flush();
      if (System.out.checkError()) throw new OutputError();
   }

   private static int getExitFailureCode() {
      try {
         return (new java.lang.ProcessBuilder("/bin/false")).start().waitFor();
      } catch (Exception dummy) {
         return 99;
      }
   }

   public static void main(String[] args) {
      try {
         println("Hello, world!");
         flush();
      } catch (OutputError dummy) {
         System.err.println("An output error occurred.");
         System.exit(getExitFailureCode());
      }
   }
}

但是,这并不是真正可移植的,因为它只能在提供“假”实用程序的POSIX系统上可靠地工作。

否则,它将返回到任意返回码99,这显然很危险,因为某些平台可以例如将所有负值定义为失败代码,而将所有其他值定义为成功代码。

2 个答案:

答案 0 :(得分:3)

System.outPrintStream

PrintStream的文档说:

  

与其他输出流不同,PrintStream从不抛出IOException;相反,在特殊情况下,只需设置可以通过checkError方法进行测试的内部标志即可。

您可以检查System.out.checkError()以查看是否发生了错误。

如果您希望程序以非零状态退出,则可以使用System.exit

例如

if (System.out.checkError()) {
    System.err.println("An output error occurred.");
    System.exit(-1);
}

另请参阅Is there a replacement for EXIT_SUCCESS and EXIT_FAILURE in Java?

答案 1 :(得分:2)

对象System.outjava.io.PrintStream的实例。您可以使用checkError()检查可能的错误。