How do streams work when code is executed step by step? - java

For example, in java, to read input from the console you would write something like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ReadConsoleSystem {
public static void main(String[] args) {
System.out.println("Enter something here : ");
try{
BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
String s = bufferRead.readLine();
System.out.println(s);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
So in the line String s = bufferRead.readLine(), the code just waits for the input to come in and then goes to the next step, but what if you want to look at a continuous stream of strings trying to parse out pieces of it, for example, reading a stream of Twitter statuses and only saving the ones that have the word "Obama" in it or something?
I don't understand how the code could be executing line-by-line, while handling input from the stream, and then suddenly detecting when input is given and saving it.

bufferRead.readLine(); doesn't return back to the calling code, until the user presses the return key.

That code write there is only set to read in one line of input, from the system's input (that is, the console). It's setup so that when you do readLine, it will read a line from the input. You have to type in something ("Hello there") and hit enter, and it will take that, and put it in String s. If you want to parse stuff out, do it manually afterwords
if(s.contains("Obama")) {
//blah
}

The console is line buffered. This means an entire line comes as once to the Java process so it doesn't see you writing characters or hitting back space to delete them etc.
I suspect you don't need to see how it does this. Perhaps you could describe what problem you are trying to solve?

Related

Java Waiting for Enter Key Solution not Working

So I've tried to implement a solution for waiting on user to press enter to continue found here: Java Console Prompt for ENTER input before moving on
However, when I try to use either of the solutions proposed I get the following errors:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at printLine.promptEnterKey(printLine.java:153)
at printLine.main(printLine.java:144)
and
java.io.IOException: Stream closed
at java.base/java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:176)
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:342)
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107)
at printLine.promptEnterKey(printLine.java:155)
at printLine.main(printLine.java:146)
I made a test program before to make sure this would work as expected and it worked fine for me:
// import scanner for user-input
import java.util.Scanner;
public class test{
public static void promptEnterKey(){
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
}
public static void main(String[] args){
promptEnterKey();
}
}
Here's my code, I am working on a program that will read the current line, print it and then wait for the user to hit enter before proceeding:
// import System.out
import static java.lang.System.out;
// import scanner for user-input
import java.util.Scanner;
// import File class
import java.io.File;
// import FileNotFoundException
import java.io.FileNotFoundException;
// delete if ioexception not used
import java.io.IOException;
/* this is the main public class */
public class printLine {
/* this method is used to execute the application */
public static void main(String[] args){
// create scanner for user input
Scanner userInput = new Scanner(System.in);
// user input for file
out.println("This program will print the text file line by line, waiting for the user to hit the enter key");
out.println("Please specify the file to print line by line: ");
String textFile = userInput.nextLine();
userInput.close();
// try to open file
try{
// load the file
File text = new File(textFile);
// for reading the file
Scanner textReader = new Scanner(text);
// while there is another token...
while (textReader.hasNextLine()){
String curLine = textReader.nextLine();
out.println(curLine);
promptEnterKey();
}// end while
// close reader
textReader.close();
}// end try
// catch FileNotFoundException error
catch (FileNotFoundException e){
out.println("File not found.");
e.printStackTrace();
}// end catch
}// end main
/* This method is for waiting for the user to press the Enter key.
this was taken from https://stackoverflow.com/questions/26184409/java-console-prompt-for-enter-input-before-moving-on */
public static void promptEnterKey(){
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
}
}// end class
Here's the sample text excerpt that I am trying to use it on:
There was nothing so VERY remarkable in that; nor did Alice
think it so VERY much out of the way to hear the Rabbit say to
itself, `Oh dear! Oh dear! I shall be late!' (when she thought
it over afterwards, it occurred to her that she ought to have
wondered at this, but at the time it all seemed quite natural);
but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-
POCKET, and looked at it, and then hurried on, Alice started to
her feet, for it flashed across her mind that she had never
before seen a rabbit with either a waistcoat-pocket, or a watch to
take out of it, and burning with curiosity, she ran across the
field after it, and fortunately was just in time to see it pop
down a large rabbit-hole under the hedge.
In another moment down went Alice after it, never once
considering how in the world she was to get out again.
The rabbit-hole went straight on like a tunnel for some way,
and then dipped suddenly down, so suddenly that Alice had not a
moment to think about stopping herself before she found herself
falling down a very deep well.
Either the well was very deep, or she fell very slowly, for she
had plenty of time as she went down to look about her and to
wonder what was going to happen next. First, she tried to look
down and make out what she was coming to, but it was too dark to
see anything; then she looked at the sides of the well, and
noticed that they were filled with cupboards and book-shelves;
here and there she saw maps and pictures hung upon pegs. She
took down a jar from one of the shelves as she passed; it was
labelled `ORANGE MARMALADE', but to her great disappointment it
was empty: she did not like to drop the jar for fear of killing
somebody, so managed to put it into one of the cupboards as she
fell past it.
Any insight as to what I'm doing wrong is appreciated.
Thanks!
JT
you are closing the userInput (System.in) immediately after reading the file name userInput.close();
move that line to the end of your code
Scanner.close will also close it's underlying readable if it implements Closable interface, in your case that is System.in input stream:
https://www.tutorialspoint.com/java/util/scanner_close.htm

Why can I not let my program run my method over and over (while loop)?

This is a diary program which allows you to write something in your diary (obviously). After typing enter and pressing enter, the page closes and its gonna be safed in a list. My problem is that it only runs once when I have Pages(); in the main method, so I tried this loop. It doesnt work for me and i dont know why. Need some help
import java.util.ArrayList;
import java.util.Scanner;
public class NotizbuchKlasse{
public static void Pages() {
System.out.println("day 1 : Write something in your diary.");
System.out.println("Write enter if you are done writing.");
ArrayList<String> List = new ArrayList<String>();
String ListInList;
Scanner write = new Scanner(System.in);
do {
ListInList = write.next();
List.add(ListInList);
} while (! ListInList.equals("enter"));
List.remove(List.size()-1);
write.close();
System.out.println("This is now your page. Your page is gonna be created after writing something new.");
System.out.println(List);
}
public static void main(String[]Args){
boolean run = true;
do{
Pages();
} while(run);
}
}
Error:
This is now your page. Your page is gonna be created after writing something
new.
Exception in thread "main" [hello]
day 1 : Write something in your diary.
Write enter if you are done writing.
java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at NotizbuchKlasse.Pages(NotizbuchKlasse.java:12)
at NotizbuchKlasse.main(NotizbuchKlasse.java:24)
You need to check whether there is something to read before you read it. You're not currently, and that's why you're getting a NoSuchElementException.
You do this via Scanner's has* methods.
For example:
ArrayList<String> List = new ArrayList<String>();
Scanner write = new Scanner(System.in);
while (write.hasNextLine()) {
String ListInList = write.nextLine();
if (ListInList.equals("enter")) break;
List.add(ListInList);
}
// No need to remove the last item from the list.
But also, I notice that you have a loop in your main method, where you call Pages() in that loop. If you close write, you also close System.in; once a stream is closed, you can't re-open it. So if you try to read things from System.in the next time you call Pages(), the stream is already closed, so there's nothing to read.
Simply don't call write.close(). You shouldn't close streams that you didn't open in general; and you didn't open System.in (the JVM did when it started up), so don't close it.
You want to be using a while loop like this:
while (write.hasNextLine()) {
ListInList = write.nextLine();
if (doneWriting(ListInList)) { // Check for use of enter.
break; // Exit the while loop when enter is found.
}
List.add(ListInList); // No enter found. Add input to diary entry.
}
where doneWriting() is a method (that you write!) which checks to see if the user has typed enter.
Here is the documentation for the next() method of Scanner. If you read it, you will see that it throws the exception you are getting when it runs out of tokens.
If you want a little bit more a casual explanation here is a question that was asked previously about next() versus nextLine().

Why am i getting a runtime error while submitting this code online?(jdk 1.7)

This is the code (used IntelliJ idea jdk 1.8)
It worked well for me but shows a runtime error whenever I submit it in an online portal (jdk 1.7). What changes should I make?
I have no idea what is causing the error.
import java.lang.String;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException{
int n,k;
int i=0;
int sum=0;
do {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine();
n = Integer.parseInt(s);
String s1 = reader.readLine();
k = Integer.parseInt(s1);
reader.close();
}while ( n<0 || k>java.lang.Math.pow(10,9) || n<k );
for (i=0 ; i<=k ; i=i+2){
sum+= fact(n)/(fact(i)*fact(n-i));
}
System.out.print(sum);
}
public static int fact(int n) {
int j=1;
while(n!=0){
j=j*n;
n--;
}
return j;
}
}
I prefer not to use Scanner
Error :
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.parseInt(Integer.java:615)
at Main.main(Main.java:18)
The stack trace is pretty clear that the problem arises from Main.main() passing null to Integer.parseInt(). It reports the parseInt() invocation appearing on line 18 of Main.java; that doesn't line up perfectly with your source as you presented it, but it's about right for this line:
n = Integer.parseInt(s);
The string s at that point was just obtained via your BufferedReader's readLine() method -- this indicates that there are no more data available from the underlying stream (ultimately, System.in).
That might be a bit surprising if it happened on the first iteration of your loop, but you close the BufferedReader yourself at the end of that iteration, and that closes all the wrapped Readers and InputStreams as well. On the second iteration, System.in is closed, and you are unable to read anything from it. You should instead initialize your BufferedReader outside the loop, and wait to close it until after you exit the loop:
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
do {
// do something with 'reader'
} while ( /* some condition */ );
reader.close();
Even if you were not closing the underlying stream, you certainly are buffering input from it, and then potentially tossing some of that buffered input along with the BufferedReader. That in itself could cause your program to observe end-of-file earlier than it expected. That might happen, for example, if you moved the close() outside the loop, but still created and read from a new BufferedReader on each iteration of the loop.
Moreover, it is wise to check upon each read whether a line was read successfully, and to handle the case where none was (indicated by null being returned). For a submission to an online solution checker, however, it might be reasonable to assume that the input will conform to your expectations.
Often when using Online IDEs / compilers, you need to type the input before you run your program. The online tools may not prompt you for input, which can lead to your variables being set to null. A null variable will cause the error you are seeing.
How exactly to fix this depends on which online tool you are using. For example, if you are using Ideone, type your input into the "enter input (stdin)" or the "input" textboxes before running your program. For your program, since you are using readLine(), put the input on separate lines, as seen in this picture.
I copy and pasted your code into Ideone. If I didn't enter anything into the input textbox, I got the same error you saw. But if I entered the input before running the program, your code ran without errors.
You have to make sure the string returned from readline() is number and not null.

Hashmap returns null only on the first try

I'm writing a simple file server that will let the user telnet in, supply a username and search for the access level given to that user, and then show a list of files and only allow them to see the contents of the file if they have a sufficient access level. This code is for the server side, I'm just using PuTTY for the client
I read the userfile in (delimited with colons to separate name and access level)
paul:10
schemm:8
bobbarker:0
with this code
static Map<String, Integer> users = new HashMap<String, Integer>();
file = new File("userfile.txt");
try
{
out.println("Reading userfile.txt");
Scanner scannerusers = new Scanner(file);
while (scannerusers.hasNextLine())
{
String line = scannerusers.nextLine();
line.trim();
String field[] = line.split(":");
users.put(field[0], Integer.parseInt(field[1]));
}
scannerusers.close();
}
catch (FileNotFoundException e)
{
out.println("userfile.txt not found!");
}
But my actual problem is here (at least I think). Both the uncommented and commented code will fail on the first attempt, but succeed on the second.
//socket connection stuff here, and all this is nested in a try-catch to get
//connection errors
while(!check)
{
outToClient.writeBytes("What is your username?");
clientinput = inFromClient.readLine();
String username = clientinput;
//
if(users.get(username) == null)
{
outToClient.writeBytes("Invalid username");
}
else
{
check = true;
}
//
//try
//{
// accesslevel = users.get(username);
// check = true; //my thinking was that the NullPointerException would be thrown
// //before this point, but either way doesn't fix the problem
//}
//catch(NullPointerException e)
//{
// outToClient.writeBytes("Incorrect username");
//}
}
Edit: I put the full source on pastebin here
I agree, this does sound like a race condition but I don't see where a race condition would come from in your code. Perhaps it's the way you open your streams? Now I haven't played with Java in a while, but if I remember right I always had the base stream, then opened an input stream reader (I think) from the base stream, then wrapped a buffered reader around that.
Try printing out the string you receive from the client, in ASCII codes. Printing out the actual string might not show some unprintable characters you might be receiving.
If it ALWAYS fails the first time, and ALWAYS succeeds the second, then it sounds like a race condition. Perhaps the file read code is triggered by the first read operation, but done in a separate thread so the calling thread continues instead of synchronously waiting for the result. We need to see the calling code to be sure.
Perhaps inFromClient.readLine() is reading more (or less) than you expect the first time around. Are you sure it is returning what you expect? I haven't used PuTTY in a while, perhaps it is sending some terminal control characters on initial connect that are getting picked up by your first read? You also don't show us the connection code, are you sending data back and forth prior to this point that is not being fully processed?

Reading lines of input from user using SCANNER

I have a program that needs to read lines of input. It needs to be many lines at once. For example:
As I enter my time machine or
maybe not,
I wonder whether free will exists?
I wonder whether free will exists
maybe not
as I enter my time machine or.
That all gets entered at one time by the user. I was trying to use .hasNextLine() method from Scanner class, but it is not returning false.... it waits for input again. Ive been looking around for a solution and it appears that .hasNextLine() waits for input, but i do not know what alternative to use. Any suggestions? The actual code looks like:
while(input.hasNextLine());
{
line += input.nextLine();
}
Thanks for your help
Perhaps you should use some sort of "stop" sequence meaning when the user enters a particular character sequence, it will break out the loop. It might look something like:
public static void main(String args[]){
final String stopSequence = "/stop";
final Scanner reader = new Scanner(System.in);
String input = reader.nextLine();
while(!input.equalsIgnoreCase(stopSequence)){
//process input
input = reader.nextLine();
}
}

Categories