JDK-8305457 : Implement java.io.IO
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.io
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2023-04-03
  • Updated: 2024-05-31
  • Resolved: 2024-05-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 23
23 b25Fixed
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Description
JEP 477 [1] (Implicitly Declared Classes and Instance Main Methods) includes some new APIs for simple text-based interaction. This issue covers the implementation of those APIs.

A new public class java.io.IO is introduced, having the following three methods:

  1. public static void println(Object obj)
  2. public static void print(Object obj)
  3. public static String readln(String prompt)

These methods are simply static adapter methods that invoke the corresponding instance methods on the result of System.console(). If System.console() returns null, these methods should throw IOError.

Instance methods with these names should be added to java.io.Console.

All of these new APIs (both the new methods on Console and the IO class) should be marked as Preview.

Some rationale follows.

IO is automatically static-imported into implicit classes, as described by the JEP. As such, these are convenience methods that shouldn't do anything that isn't possible on Console itself. While they could be entirely implemented in terms of existing Console methods (e.g., printf and readLine) these methods have their own purpose and it makes sense to have them directly as instance methods on Console as well.

There is no need for the primitive overloads of print and println that are present on PrintStream and PrintWriter. First, we have autoboxing, so overloads aren't necessary to remove source code clutter. Second, the overhead of boxing is inconsequential compared to the overhead of performing console I/O, so it's not worth adding API clutter in an attempt to improve performance.

Console already has readLine() method; why have readln()? The goal is to have a method that prints a prompt and reads a line. The readLine() methods mostly fit this bill. However, the no-arg version of readLine() reads a line *without* issuing a prompt, which could be confusing for beginners. The other overload readLine(fmt, args...) takes a *format string* followed by optional arguments. We want the prompt to be a plain string, not a format string. If a readLine(String plainString) overload were added, it would mean that additional arguments would change the semantics of the first argument. This is bad overload API style and should be avoided.

The name "readln" was chosen over the alternative "input" because it's a better verb, its naming is evocative of "println" which is already used elsewhere in the JDK, and "readln" is something of an homage to Pascal.

These methods are specified in terms of Console for the following reasons. First, the goal here is to introduce "convenience methods" that are entirely implemented in terms of other mechanisms. These methods shouldn't introduce any new logic or abstractions. They should be thin layer over existing APIs.

Second, these methods need to be specified in terms of *something*; the choices are System.in plus System.out or Console. The behaviors cannot be left unspecified (either explictly or implicitly), because operations that include buffering and flushing are intrusive with respect to the underlying mechanism in use. If, for example, readln() were implemented in terms of System.in, by wrapping it in a BufferedReader, then direct use of System.in would have unpredictable behavior because of the buffering.

Third, Console was chosen because it's an API that fuses input and output. The readln(prompt) method needs to emit the prompt, flush the output, and then read input. In addition, the Console abstraction allows an enhanced input experience such as line editing and history. If these methods were defined in terms of System.in+System.out, then readln(prompt) would need to be specified to have various side effects on System.out as well as System.in. There are also a variety of decisions made in Console that would need to be reimplemented or respecified if these methods were based on System.in+System.out.

Some additional cleanups to Console are necessary though. For example, the behavior of Console when stdin or stdout is redirected should be specified. The circumstances under which System.console() returns null (and these methods throw IOError) should also be narrowed. For example, one case where this might be reasonable is if System.in or System.out are closed. Finally, Console should be specified to be an abstraction around System.in and System.out, and not something like /dev/tty or CON: on Windows. While an interactive Console might imply that the implementation should go directly to /dev/tty, this is rare and unusual behavior for programs. Historically Console has not done this and has attempted to use System.in and System.out. Finally, we do want to support redirection, which is not available if something like /dev/tty or CON: were used.

[1]: https://openjdk.org/jeps/477
Comments
I created JDK-8333358 and added some info about the expect version . It fails on a number of machines, not just 1 or 2 .
31-05-2024

[~mbaesken] Can you create a new issue for the test failures you are seeing, and include the version of /usr/bin/expect as it may be something to do with that (which would explain why we don't see the failures on our systems).
31-05-2024

java/io/IO/IO.java generates a lot of test failures since it has been introduced. Should we problem list the test for now ? The failures are seen on Linux and macOS.
31-05-2024

Changeset: c099f14f Author: Pavel Rappo <prappo@openjdk.org> Date: 2024-05-24 13:37:14 +0000 URL: https://git.openjdk.org/jdk/commit/c099f14f07260713229cffbe7d23aa8305415a67
24-05-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/19112 Date: 2024-05-06 21:45:12 +0000
06-05-2024

Updated the Description to provide background on the changes and to provide additional rationale.
01-05-2024

Changed the title and summary to reflect the latest thinking on that issue.
01-05-2024

The most up-to-date discussion is happening on this PR page which is currently in _draft_ state: https://github.com/openjdk/jdk/pull/18921 Note: the sandbox branch (mentioned in the comments above) is no longer up-to-date.
25-04-2024

I'm repurposing this RFE to reflect current thinking on the design. For easy reference, the previous issue summary and description are copied below. Summary: java.io.SimpleIO - common I/O tasks simplified Description: In unison with the Amber onramp project, there are many mundane I/O tasks that leave developer searching StackOverflow for the appropriate idiom. The intent of the java.io.SimpleIO class is to package these idioms as easy to use static methods. - read/write from/to the console - read/write from/to (UTF-8) text files These methods should not require wrapping in try blocks, but allow the handling of UncheckedIOExceptions.
17-04-2024

I committed the initial version here: https://github.com/openjdk/jdk-sandbox/tree/JDK-8305457-branch
19-02-2024

See also JDK-6852033.
03-04-2023