0

I have some multiline text as a console input. Something like that:

first string with some text
second string with another text
third text with its own text

Number of lines may be different (one, two, three, four, etc., but not zero) every time, but this text is always putted in an instant with line separators (one pasting, not several inputs with pressing the enter key). This Java app has to immediately start to do something with those lines, but for some reason I can't understand, how to make this behavior. I mean, it has to save all these lines into String, or String[], or List<String>, or something else. If it's possible, I also would like to know, how to do this for "paste multiline text and Enter" input, but the main thing is for "paste multiline text (and no Enter)".

Of course, I tried to do that with Scanner, but I can't find working solution. It either gives me only the first line, or it doesn't understand, that the last line is the last one waiting for the next input.

Irimitlad
  • 59
  • 1
  • 6
  • It seems like this is not possible. Don't you think? – hfontanez Feb 26 '22 at 14:20
  • Well, maybe, but then it's extremely weird. It looks like some common task. And for me that answer is something really bad, but what can I do. – Irimitlad Feb 26 '22 at 14:35
  • It's not `System.in` you are waiting for, but the terminal software of the operating system. It simply doesn't send a line to any program, including Java programs, until you press Enter. You can usually edit the line until then. Related: https://stackoverflow.com/questions/1066318/how-to-read-a-single-char-from-the-console-in-java-as-the-user-types-it – tevemadar Mar 01 '22 at 13:06
  • It's worth keeping in mind that for similar reasons in many computing environment a line of text is considered being a line of text if it ends with a newline character sequence. – tevemadar Mar 01 '22 at 13:08

1 Answers1

2

There are two ways I can think of to make your scanner stop waiting for input and save your whole string as entered.

The first approach is to input your text into the console, hit Enter and then press CTRL+D, which will add an endline character. This endline character will make the scanner.hasNextLine() method return false, and therefore it will stop waiting for input. The code for this is pretty straightforward:

Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
    sb.append(scanner.nextLine()).append("\n");
}
sb.deleteCharAt(sb.length() - 1); // delete the last \n character
String s = sb.toString();

Using this approach, even though your input is a whole multiline string, it will be read line by line using the scanner.nextLine() method. Each line will be appended to the StringBuilder, plus a newline character \n to keep the original input. As you can see, I then easily converted the sb into a String s.

StringBuilder is the recommended way of composing a string from multiple parts.

The second approach does not require CTRL+D and it is very similar to the first one. The addition is that every line of input is checked to see if it is empty, using the line.isEmpty() method. If it is empty, you'll simply break from the while loop without that line being appended to the sb:

Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    if (line.isEmpty()) {
        break;
    } // else
    sb.append(line).append("\n");
}
sb.deleteCharAt(sb.length() - 1); // delete the last \n character
String s = sb.toString();

Now, this approach will obviously not work if your input contains empty lines in it (like breaks between paragraphs), because it will stop there and the rest of the string will be left out. However, instead of if (line.isEmpty()) you can decide on a stopping character and check if the line starts with it. If so, break:

if (line.startsWith("&")) { 
    break;
}

Again, this character won't be included in your sb. Have a good one!

holovii
  • 71
  • 1
  • 4
  • The second solution almost works, but still not what I need. It still requires one extra key, that is forbidden, because that's not me, who would use this app, and such weird input is described strictly in a specification. Anyway, thank you! – Irimitlad Feb 26 '22 at 16:13
  • 1
    "_so you don't keep creating copies like you would using the immutable String._" - Are you certain about this? I can tell you for certain that this statement is incorrect. You should research "_string concatenation runtime optimization in Java_". – hfontanez Feb 26 '22 at 17:31