Можно ли написать правильный и переносимый консольный вывод «hello world» в JAVA?

Я новичок в 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, что, очевидно, опасно, поскольку некоторые платформы могут, например, определить все отрицательные значения как коды ошибки, а все остальные значения как коды успеха.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
3
108
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Объект System.out является экземпляром java.io.PrintStream. Вы можете использовать checkError() для проверки возможных ошибок.

Ответ принят как подходящий

System.out есть PrintStream.

Документы для PrintStream говорят:

Unlike other output streams, a PrintStream never throws an IOException; instead, exceptional situations merely set an internal flag that can be tested via the checkError method.

Вы можете проверить System.out.checkError(), чтобы узнать, произошла ли ошибка.

Если вы хотите, чтобы ваша программа завершилась с ненулевым статусом, вы можете использовать System.exit.

Например.

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

См. также Есть ли замена EXIT_SUCCESS и EXIT_FAILURE в Java?

Другие вопросы по теме