Just started to learn Java. They gave a simple little problem, but in order for the program to react to user errors. The task here is: Create a linear program that prints the value true if the specified statement is true and false otherwise: The sum of the first two digits of the given four-digit number is equal to the sum of its last two digits. numbers I made it so that initially the number entered from the keyboard type String. Then translate into an array of Char. And actually my question. Is it possible that after introducing 4 characters of the array into the console, the program automatically starts (without Enter).

    1 answer 1

    Since it is not entirely clear what exactly you mean by launching the program, I will answer two possible interpretations of the question.

    Terminal management before launch

    If you assume that the operating system will start the JVM at the moment when you write the last character of the following command:

    $ java com.example.Main 4532 

    then unfortunately it is incredibly difficult to do and strongly depends on the operating system’s terminal settings provided and you cannot do it from your program, since control of your program will not be transferred until it is launched, and you want to change the startup behavior.

    Terminal management inside the program

    Now consider another option. Suppose you run your application of arguments, after which the user sees a sentence to enter a four-digit number:

     $ java com.example.Main Enter 4-digit number: 

    And in this case, we consider the task to start processing the input data as soon as the user enters 4 digits.

    The short answer is "Yes, it is possible." In principle, in programming, any behavior is possible to implement. However, the answer will not be cross-platform until you take care of it, or do not use a library that already cares about it. For example, jCurses will provide the necessary functionality.

    Why do I even speak about the need to provide a specific platform? The fact is that System.in connects to the system terminal, which in most cases, by default, implements input buffering, that is, it sends input data to the program after entering user input.

    If a healthy curiosity of a programmer leads you to realize the desired behavior, let's write a naive (and, therefore, the shortest) working version from which you can begin to satisfy curiosity.

    Immediately, I can write with you a program that will implement the behavior you need on unix-like systems. I apologize in advance for ignoring the canonical error handling rules of I / O systems: I am sure that you are able to independently supplement the program to a safe option.

    Let's start with the implementation of the method of reading n digits from the stream:

     private static char[] readInRawMode(int numberOfCharacters, InputStream stream) throws IOException { char [] result = new char[numberOfCharacters]; InputStreamReader is = new InputStreamReader(stream); int characterCount = 0; while (characterCount < numberOfCharacters) { char aChar = (char) is.read(); if (aChar < '0' || aChar > '9') { //ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ, Ρ‡Ρ‚ΠΎ это Ρ†ΠΈΡ„Ρ€Π° continue; } result[characterCount] = aChar; characterCount++; } return result; } 

    If we now use this method in a program, for example readInRawMode(4, System.in) , then the is.read() call is.read() blocked until the user presses enter . In order to avoid this behavior, we need to switch the current system terminal to raw mode before calling the method and return it to cooked mode after the processing method completes. In raw mode, the terminal does not repeat the characters entered by the user on the screen (as when entering a password in the terminal) and we must do it ourselves. Moreover, the raw terminal will no longer respond to special characters including the carriage return character and the user’s enter will also be ignored and not displayed until he has entered the required number of digits. This is exactly the behavior that suits us.

    Putting it all together we get something like this:

     package com.alex; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException, InterruptedException { System.out.print("Enter 4-digit number : "); char [] input = interactiveRead(); System.out.println(); System.out.println("User input: " + Arrays.toString(input)); } private static char[] interactiveRead() throws IOException, InterruptedException { String[] raw = {"/bin/sh", "-c", "stty raw </dev/tty"}; //ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»Π° Π² Ρ€Π΅ΠΆΠΈΠΌ raw String[] cooked = {"/bin/sh", "-c", "stty cooked </dev/tty"}; //ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»Π° Π² Ρ€Π΅ΠΆΠΈΠΌ cooked Process p = Runtime.getRuntime().exec(raw); p.waitFor();//ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»Π° try { return readInRawMode(4, System.in); } finally { p = Runtime.getRuntime().exec(cooked); //Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π» ΠΊ ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΌΡƒ Π²ΠΈΠ΄Ρƒ Π²Π½Π΅ зависимости ΠΎΡ‚ ошибок p.waitFor(); } } private static char[] readInRawMode(int numberOfCharacters, InputStream stream) throws IOException { char [] result = new char[numberOfCharacters]; InputStreamReader is = new InputStreamReader(stream); int characterCount = 0; while (characterCount < numberOfCharacters) { char aChar = (char) is.read(); if (aChar < '0' || aChar > '9') { continue; } System.out.print(aChar); // повторяСм "ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ" символ Π½Π° экранС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ понял Ρ‡Ρ‚ΠΎ ΠΎΠ½ всС Π΄Π΅Π»Π°Π΅Ρ‚ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ result[characterCount] = aChar; characterCount++; } return result; } } 

    Discussion and comments

    In fact, in most cases it makes no sense to write the complex logic of the "rich" user interaction with the terminal. This gives a strong complication to the application logic (what we just described is not enough: you need to take care of execution errors and control commands such as ^ C in the terminal), and the profit is minimal: in the modern world, users prefer graphical interfaces, and people used to working with the terminal and so they will understand what is happening and what exactly you need to enter: these are people of a technical mentality.

    I also want to note that the written application is sharpened to start from the terminal by hand and only then it will work correctly. In the case of launching through IDE, its native terminal will not be transferred to the required mode, since it uses not a standard system terminal, but its wrapper, which also implements buffering. I hope this makes it even more understandable to write a universal solution for your problem.

    • Thank you very much for the detailed answer!) - AlKlejm
    • For such answers, I loved StackOverFlow. Thanks, it was interesting to read! - Michael Kolbasov