Multiline console input in Java - java

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.

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!

Related

Java Scanner, No such element exception while reading mulitple lines

I am trying to read multiple line from a file using java scanner. Each line has strings separated using comma, but there is no comma at the end of line. My text file contains value like below
98792203000000005091,89065012012341234100000000000167,084952103900000015
98792203000000005091,89065012012341234100000000000167,084952103900000015
The scanner is throwing a no element exception, it works fine if I add a comma t the end of line, but the original file will not have a comma. How do I make work
Scanner sc = new Scanner(outPutFile);
int outputDataStart = Integer.parseInt(outputDataStartLine);
skipLines(sc, outputDataStart);
sc.useDelimiter(",");
while(sc.hasNext())
{
OutputVariables outputVariables = new OutputVariables();
outputVariables.setIccid(sc.next());
outputVariables.setImsi(sc.next());
outputVariables.setKey(sc.next());
outputVariables.setPIN1(sc.next());
outputVariables.setPUK1(sc.next());
outputVariables.setPIN2(sc.next());
outputVariables.setPUK2(sc.next());
outputVariables.setPINAdm(sc.next());
outputVariables.setAccount(sc.next());
outputVariables.setKIC(sc.next());
outputVariables.setKID(sc.next());
outputVariables.setKIK(sc.next());
outputVariables.setOPCKey(sc.next());
OutputVariableList.add(outputVariables);
}
Insteard of using sc.useDelimiter(",") use sc.useDelimiter(",|\\n") it would break by both , and new line
You're asking the scanner to parse more values from a line of text than there are values. This is happening because you're calling next() without first checking hasNext(). Since you've told it to use the comma as the delimeter, it's hitting the end of the line continuing on to the next line until it finds the next comma.
Consider this CSV:
A,B,C,D
If you call next() after you parse the "D", the scanner will throw a NoSuchElementException.
It is not clear what you're attempting to do. If you're attempting to convert what is effectively a CSV into an object, then your best bet would be to use the Scanner to read each line, and then a String.split() call to split that line into parts.
If you're trying to parse multiple lines into an object, you'll of course need to figure out where your boundary is -- every fifteen comma separated values? every three lines? -- and apply that logic while collecting your segments.
As a simplified example, consider this collection of lines:
A,B,C,D
E,F,G,H
I,J,K
You would first use the Scanner to read line-by-line, and then use split each line apart and create the individual objects. Notice the last line is malformed -- you'll need to trap for that and catch it to avoid the NoSuchElementException.
Scanner sc = new Scanner(file);
while(sc.hasNext()) {
String line = sc.next();
String[] parts = line.split(",");
if(parts.length != 4) {
System.err.println("Invalid line: " + line);
continue; // skip this record, it is bad
}
// create your object here from parts
Pojo example = new Pojo(parts[0], parts[1], parts[2], parts[3]);
// etc
}
Alternatively if you're just trying to create a single massive object -- eg all lines belong to the same record -- you could tell it to consider a newline as a delimeter in addition to a comma. That way, after you hit the last comma in the first line, you would call next() and it would parse until the end of the line; and then when you called next() again, it would parse starting on the next line until it reached a comma or the end of the line, whichever came first.
I suggest you to use BufferedReader
it has a method named readLine()
first read a String then through the string.split(",") you can get the array of String

Is there a way around not advancing a line with Scanner (Java)

Okay so I'm having a slight problem with scanner advancing an extra line. I have a file that has many lines containing integers each separated by one space. Somewhere in the file there is a line with no integers and just the word "done".
When done is found we exit the loop and print out the largest prime integer that is less than each given integer in each line(if integer is already prime do nothing to it). We do this all the way up until the line with "done".
My problem: lets say the file contains 6 lines and on the 6th line is the word done. My output would skip lines 1, 3 and 5. It would only return the correct values for line 2 and 4.
Here's a snippet of code where I read the values in:
Scanner in = new Scanner(
new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while(in.nextLine() != "done"){
String[] arr = in.nextLine().split(" ");
Now I sense the problem is that the nextLine call in my loop advances the line and then the nextline.split call also advances the line. Thus, all odd number lines will be lost. Would there be another way to check for "done" without advancing a line or is there a possible command I could call to somehow reset the scanner back to the start of the loop?
The problem is you have 2 calls to nextLine() try something like this
String line = in.nextLine();
while (!"done".equals(line)) {
String[] arr = line.split(" ");
// Process the line
if (!in.hasNextLine()) {
// Error reached end of file without finding done
}
line = in.nextLine();
}
Also note I fixed the check for "done" you should be using equals().
I think you are looking for this
while(in.hasNextLine()){
String str = in.nextLine();
if(str.trim().equals("done"){
break;
}else{
String[] arr = str.split("\\s+");
//then do whatever you want to do
}
}

Why my method being called 3 times after System.in.read() in loop

I have started to learn Java, wrote couple of very easy things, but there is a thing that I don't understand:
public static void main(String[] args) throws java.io.IOException
{
char ch;
do
{
System.out.println("Quess the letter");
ch = (char) System.in.read();
}
while (ch != 'q');
}
Why does the System.out.println prints "Quess the letter" three times after giving a wrong answer. Before giving any answer string is printed only once.
Thanks in advance
Because when you print char and press Enter you produce 3 symbols (on Windows): character, carriage return and line feed:
q\r\n
You can find more details here: http://en.wikipedia.org/wiki/Newline
For your task you may want to use higher level API, e.g. Scanner:
Scanner scanner = new Scanner(System.in);
do {
System.out.println("Guess the letter");
ch = scanner.nextLine().charAt(0);
} while (ch != 'q');
Using System.in directly is probably the wrong thing to do. You'll see that if your character is changed from q to something in Russian, Arabic or Chinese. Reading just one byte is never going to match it. You are just lucky that the bytes read from console in UTF-8 match the character codes for the plain English characters.
The way you are doing it, you are looking at the input as a stream of bytes. And then, as #Sergey Grinev said, you get three characters - the actual character you entered, and the carriage return and line feed that were produce by pressing Enter.
If you want to treat your input as characters, rather than bytes, you should create a BufferedReader or a Scanner backed by System.in. Then you can read a whole line, and it will dispose of the carriage return and linefeed characters for you.
To use a BufferedReader you do something like:
BufferedReader reader = new BufferedReader( InputStreamReader( System.in ) );
And then you can use:
String userInput = reader.readLine();
To use a Scanner, you do something like:
Scanner scanner = new Scanner( System.in );
And then you can use:
String userInput = scanner.nextLine();
In both cases, the result is a String, not a char, so you should be careful - don't compare it using == but using equals(). Or make sure its length is greater than 1 and take its first character using charAt(0).
As has been mentioned, the initial read command takes in 3 characters and holds them in the buffer.
The next time a read command comes around, it first checks the buffer before waiting for a keyboard input. Try entering more than one letter before hitting enter- your method should get called however many characters you entered + 2.
For an even simpler fix:
//add char 'ignore' variable to the char declaration
char ch ignore;
//add this do while loop after the "ch = (char) System.in.read();" line
do{
ignore = (char) System.in.read();
} while (ignore != '\n');
this way 'ignore' will cycle through the buffer until it hits the newline character in the buffer (the last one entered via pressing enter in Windows) leaving you with an fresh buffer when the method is called again.

How to print characters as user inpt them in console and stop when user enters enter character java

I am trying to write a method that prints out whatever character the user is entering character by character appended with the previous ones as he enters and throws an exception when he presses enter. I have written the following code but when i enter, it appends what ever character I have written and does not throw an exception. I would appreciate your help and suggestion.
public static void inputM(StringBuffer a) throws EntExc, IOException{
char c;
String m;
while(true){
Scanner s = new Scanner(System.in);
m=s.next();
c=m.charAt(0);
if(c=='\r'){
throw new EntExc();
}
System.out.println(a.append(m));
}
}
There are a few issues here. First s.next() grabs a whitespace-delimited token and returns the entire token as a single string. Second, because Scanner uses whitespace as a delimiter, it will never return \r, it will just skip it and read the next token.
Why not use s.readLine() and simply echo the whole line? While it won't process characters as they are entered (Scanner can't really do this, it always buffers lines), it will be closer to your described requirement.

Text with "return" in it - Java scanner input

This is my code:
Scanner scan = new Scanner(System.in);
String speed_string = scan.nextLine();
String[] string_array = speed_string.split("\\s");
I want my code to handle newlines, such as copy-pasting two or more paragraphs into a single nextLine. Is that possible? As it is currently, it will take in whatever the input until the newline.
It will stop at the newline, as per the API states:
Since this method continues to search through the input looking for a
line separator, it may buffer all of the input searching for the line
to skip if no line separators are present
So no, you cannot paste a big block and expect it to take it at once.
See nextLine method
You can't change the fact that nextLine() returns one line. that's its whole purpose. You can read two lines and combine those two strings, though. Of course that means some knowledge of the file format.
There is no possibility to do that using Scanner class because it can only read line confirmed by 'enter' or newline sign.
But you can also handle concatenating two lines using ArrayUtils.
Scanner scan = new Scanner(System.in);
String speed_string = scan.nextLine();
String speed_string1 = scan.nextLine();
String[] string_array = speed_string.split("\\s");
String[] string_array1 = speed_string.split("\\s");
String[] both = ArrayUtils.addAll(string_array , string_array1 );

Categories

Resources