Я новичок в JAVA и пока не нашел способа написать приложение "hello world", которое правильно работает без каких-либо изменений на всех платформах, а также обнаруживает и обрабатывает ошибки вывода.
В частности, я хотел бы перенести следующую переносимую программу C на JAVA:
«Макетфайл»:
.POSIX:
TARGETS = hello
.PHONY: all clean
all: $(TARGETS)
clean:
-rm $(TARGETS)
"Привет":
#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(), похоже, не проверяют ошибки ввода-вывода, или, может быть, я просто не смог их отловить.
Я уже пробовал ловить исключения типа IOException, но компилятор мне говорит, что
error: exception IOException is never thrown in body of corresponding try statement
так что это явно не правильный способ сделать это.
Но даже если бы я мог найти способ перехватывать ошибки вывода, я все еще не знал, какой код выхода использовать для переносимости, потому что JAVA, похоже, не определяет что-то, соответствующее EXIT_FAILURE C.
Мне трудно в это поверить, учитывая, что JAVA всегда хвалили как переносимую систему для разработки приложений.
Было бы довольно шокирующе, если бы правильная и портативная реализация даже простого «hello world» уже превзошла возможности этой платформы «напиши один раз, работай везде».
Поэтому, пожалуйста, помогите мне создать реализацию JAVA, которая ведет себя точно так же, как версия C, и при этом является переносимой.
Благодаря 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, что, очевидно, опасно, поскольку некоторые платформы могут, например, определить все отрицательные значения как коды ошибки, а все остальные значения как коды успеха.




Объект System.out является экземпляром java.io.PrintStream. Вы можете использовать checkError() для проверки возможных ошибок.
System.out есть PrintStream.
Документы для PrintStream говорят:
Unlike other output streams, a
PrintStreamnever throws anIOException; instead, exceptional situations merely set an internal flag that can be tested via thecheckErrormethod.
Вы можете проверить System.out.checkError(), чтобы узнать, произошла ли ошибка.
Если вы хотите, чтобы ваша программа завершилась с ненулевым статусом, вы можете использовать System.exit.
Например.
if (System.out.checkError()) {
System.err.println("An output error occurred.");
System.exit(-1);
}
См. также Есть ли замена EXIT_SUCCESS и EXIT_FAILURE в Java?