I want to output a question to the console and then get the next line of input after the question was output.
For example, my program could be sleeping or doing some time-consuming computation, and while the user is waiting they might decide to type some notes into the console (perhaps without hitting enter, or perhaps over several lines). Once the sleep is completed, the program then asks the user a question, "What is your name?" and then it should wait for the next line of input containing the user's name, and ignore any random notes the user made while the sleep was going on.
Here's some code that tries to do that:
public static void main(String[] args) throws InterruptedException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
System.out.println("What is your name?");
// while (scanner.hasNext()) {
// scanner.nextLine();
// }
String name = scanner.nextLine();
System.out.println("Hi, " + name);
}
This behaves as follows when I type a couple of lines during the sleep:
gpeo
hpotWhat is your name?
Hi, gpeo
The problem is that scanner will read the next input continuing from the last input it read, not from the last System.out.println() (which makes sense). The commented out code tries to rectify that problem by reading past all earlier input first, then waiting on one more line to assign to name. However, scanner.hasNext() does not work as I was hoping, since when there is no next token it does not simply return false but waits for another token (so I don't know why it bothers to return a boolean at all).
Another thing that baffles me is that during the sleep if you type stuff on a single line, that single does in fact get ignored:
brbr irgjojWhat is your name?
A
Hi, A
I thought it was going to output Hi, brbr irgjojA, so that makes me think I might be misunderstanding how console input and Scanner work.
Edit: The last example was from a run within IntelliJ. When I run from my Bash commandline instead I get Hi, brbr irgjojA. The output of the first example does not change though.
Also, I was asked if this question is the same as this, and apparently I have to explain why it's not here or it will appear on the question. The issue in that post (and others like it) is that he/she is mixing scanner.nextLine() with scanner.nextInt() and similar methods that do not read the whole line or the line ending. I am only using nextLine() to read input, and my issue is quite different.
Further edit
I managed to discard the first line of random notes based on this answer to another question. Here is the new code:
public static void main(String[] args) throws InterruptedException, IOException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
System.out.println("What is your name?");
while (System.in.available() > 0) {
scanner.nextLine();
}
String name = scanner.nextLine();
System.out.println("Hi, " + name);
}
Here are some test runs in IntelliJ:
grgWhat is your name?
A
Hi, A
ghr
rhWhat is your name?
A
Hi, A
rghr
hrh
htWhat is your name?
Hi, hrh
uirh
iw
hjrt
sfWhat is your name?
Hi, iw
And here are similar tests in Bash:
htrWhat is your name?
A
Hi, htrA
rgj
hrWhat is your name?
A
Hi, hrA
rjkh
ry
jWhat is your name?
Hi, ry
ryi
rj
rd
jrWhat is your name?
Hi, rj
As you can see, the line inside the while loop never appears to get executed more than once for some reason. I tried adding a sleep inside the loop or using other InputStream methods like skip() and readAllBytes(), but these didn't seem to help at all.
I think there might not be anything one can do about the incomplete line that is a problem for Bash, but I'm sure there must be a way to throw out all the completed lines (rather than just the first one). The solution doesn't have to use Scanner, it should just behave as intended.
The Scanner uses a buffer. It’s default size is 1024 characters. So by the first nextLine() call, it reads up to 1024 of the available characters into the buffer. This is necessary, as the Scanner doesn’t even know how many characters belong to the next line, before filling the buffer and searching for a line break in the buffer.
Therefore, if there are less pending characters than the buffer size, the loop will iterate only once. But even when there are more characters, and more loop iterations, the resulting state likely is to have some pending lines in the buffer.
As long as the Scanner’s buffer is in its initial empty state, you can flush the source stream directly, instead of using the scanner:
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
while(System.in.available() > 0) {
System.in.read(new byte[System.in.available()]);
}
System.out.println("What is your name?");
String name = scanner.nextLine();
System.out.println("Hi, " + name);
Note that it would be natural to use System.in.skip(System.in.available()); instead of read, but while trying it, I encountered a bug that the underlying stream did not update the available() count after a skip when reading from a console.
Note that if the Scanner is not in its initial state but has some buffered content already, there is no way to flush the buffer, as its API is intended to make no distinction between buffered and not yet buffered, so any attempt to match all content would result in reading from the source (and blocking) again. The simplest solution to get rid of the buffered content would be
scanner = new Scanner(System.in);
Related
String fileName;
Scanner nameReader = new Scanner(System.in);
System.out.println("Enter a file name");
fileName = nameReader.nextLine();
Scanner scan = new Scanner(new FileReader(fileName));
For the code above, my professor told me that the FileReader esentially reads in data from the file to the Scanner's buffer. Then, we can access the data from the buffer using the next method, nextLine method, etc.
My question is, does the last line in the code provided above automatically and immediately fill scan's buffer with data read in from the file? I was confused by his statement, as I thought we would have to use some method for this to occur.
For the code above, my professor told me that the FileReader esentially reads in data from the file to the Scanner's buffer.
That suggests a slight misunderstanding. The FileReader has no particular knowledge of the Scanner, and cannot proactively do anything to or with it. The agency goes in the other direction: the Scanner uses the FileReader to fill its own buffer.
My question is, does the last line in the code provided above automatically and immediately fill scan's buffer with data read in from the file? I was confused by his statement, as I thought we would have to use some method for this to occur.
Probably not, but that's up to the Scanner. Do remember that one of its constructors will run, and it is entirely reasonable to consider constructors a special kind of method. In that sense, you are using a method of the Scanner, and it has an opportunity to eagerly fill the Scanner's buffer.
In any case, there is no public method whose specific purpose is to fill the buffer. Whether or not the constructor fills the buffer, the methods that scan data will (re)fill the buffer at need.
For the code above, my professor told me that the FileReader essentially reads in data from the file to the Scanner's buffer.
I think you misheard / misremembered your professor. Or maybe, they "mispoke".
A more accurate characterization is that the (second) Scanner reads from the file by calling methods on the FileReader. The FileReader has no knowledge of the Scanner that uses it ... yet alone that the Scanner has (or may have) an internal buffer of some kind.
It is important to note that we have two Scanner objects in the example. They respectively getting information from two different sources. One reads from standard input, and the the second one from a file.
My question is, does the last line in the code provided above automatically and immediately fill scan's buffer with data read in from the file?
The answer is:
In practice, No. Current implementations of Scanner will not perform the first read from the FileReader until your application actually calls a method on the Scanner object; e.g. a next or hasNext method. The constructor won't do it.
In theory it is possible. The javadoc is not crystal clear on this point. It clearly says that a number of "scanning operations" may block waiting for data, which implies that they may read data from the underlying data source. But it does NOT say anything about whether the constructors may or may not block.
I imagine that a vast amount of real world Java code has been written on the (IMO) reasonable assumption that a Scanner constructor will not try to preread data. There is zero chance that Scanner will be changed to do this.
Honestly, I don't know if I understand your question well
But if you want to use the scanner to read from a file, the following code reads and prints all the lines in the file in the desired path
try {
String path = "your file path";
FileReader fileReader = new FileReader(path);
Scanner input = new Scanner(fileReader);
while (input.hasNextLine()) {
String line = input.nextLine();
System.out.println(line);
// stuff
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
We need to make something of a lexical analyzer, and I have had some trouble with a particular function of mine, useLoad, or more accurately, what happens in Main after useLoad is used.
I figured out that that was because...for some reason, buffer=keyboard.nextLine() is throwing the error, because it's not getting more input from the keyboard for some reason. I thought that .nextLine() should force it to get more input from the user. And I don't know why it's throwing that exception specifically after this one particular method. It can do other methods just fine and not lose its ability to read. Is it because I have a variable called keyboard in another object and closed it? That seems doubtful. Just tried changing the name. Didn't make a difference.
Variables used but not declared in the below code: Keywords[0] is the String "load ". initial = the scanner string that's passed in to the function. offset = a counter variable, to see how far in to the line we've read.
The useLoad function (which is what I think is messing up somehow), is at the bottom, but I included everything it runs through (with each method separated by a horizontal rule), in chronological order, just in case I'm just not seeing what's going on.
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in); //the scanner for keyboard
int i = 0;
String buffer ="";
boolean loopControl == true;
SymbolTable mySym = new SymbolTable();
System.out.println("READY FOR INPUT\n");
while (loopControl == true){
//read in the line
buffer = "";
buffer = keyboard.nextLine();
if(!mySym.checkStop(buffer)){ //if we didn't stop
mySym.primary(buffer);
}
else{//if we did stop
closeLoop();
}
if (i >= 55){
loopControl = false;
System.out.println(("You have gone over the limit ("+i+" lines) per execution. Please continue by running this program again.").toUpperCase());
//just a safety precaution...you know... in case closeLoop doesn't work
}
i++;
}
keyboard.close();
}
if(initial.substring(0, Keywords[0].length()).equals(Keywords[0])){ //Load
//if this is working as expected, then we simply need to do what the keyword says to do.
offset += Keywords[0].length(); //we have moved this much deeper in to the line
useLoad(offset, initial);
offset = 0; //just make sure, once we are done with the line, we start back at the start of the next line.
return; //we found what we were looking for, get out.
}
private void useLoad(int offsetIn, String readIn) {
double doubIn = 0;
//now get the value of the
Scanner keyboard = new Scanner(System.in); //the scanner for keyboard
System.out.println("\nENTER VALUE FOR " + readIn.toUpperCase());
doubIn = keyboard.nextDouble();
keyboard.close();
variables.create(readIn.substring(offsetIn), doubIn);
}
I think I've figured out your problem.
Java docs for both Java 7 and 8 include this line in Scanner's close method documentation:
If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked.
Looking into the docs for System, I've found that System.in is of type InputStream which, you guessed it, implements Closeable. The close method documentation for InputStream says that it does nothing; however, InputStream is abstract and close is not marked as final, which means it can be overridden. System.in returns an InputStream which could potentially - and clearly does - do something.
So the problem is, you are creating multiple Scanners with System.in, and each time you close any one of them, you close System.in, rendering it useless!
This problem has actually been discussed in another question here, with a solution given. That said, for your program I would suggest one of two approaches:
The first approach is mentioned there: Either use a pre-made wrapper class or make your own, which accepts an InputStream in its constructor. Have this class' InputStream implementation call all the methods of its wrapped object, except for the close method which is a no-sell, and then pass Wrapper(System.in) to Scanner instead of System.in directly. However, I would be wary of taking this approach except in very specific circumstances, because any time you use one of these wrappers you would need to remember to close its wrapped object at the end of its use, unless it's something like System.in.
Second approach: Use a runner class in your program, and initialize the scanner there. Pass the scanner into the required objects during construction for them to hold a reference to, and then allow them to complete their required tasks without closing Scanner within the class. Once the exit condition is specified, return to the runner class and close Scanner from there.
You close the keyboard each time round the loop. Therefore the second time around you read from a closed keyboard object.
A quick look at the documentation for Scanner.nextLine contains the news that it might throw:
NoSuchElementException - if no line was found
I am reading input from Standard input. My input data has multiple lines, the first line has the total number of records, and from the second line, records begin. Every line is a record. We will have n+1 lines. So I want to read the number of first line with nextInt(). Here's my code:
Scanner scanner = new Scanner(System.in);
//read number of lines for scanner to break loop
int numRecords = 0;
if (scanner.hasNextInt()){
numRecords = scanner.nextInt();
...
}
But, in debug mode, each time I press F6, I see scanner.next() change. When I have the following lines of testing data as input:
3
1,1,bugs#bunny.com,123 Sesame St.,New York,NY,10011,12345689010
2,1,elmer#fudd.com,123 Sesame St.,New York,NY,10011,10987654321
3,2,bugs#bunny.com,123 Sesame St.,New York,NY,10011,12345689010
When I reach line 3 of my code,
int numRecords = 0;
scanner.next() is 3. But, when it reaches line 4,
if (scanner.hasNextInt()){
it's 1,1,bugs#bunny.com,123, so the if condition will never be true because scanner.next() is not 3. The next time I press F6, it changes to Sesame.
This is not the expected behaviour. Why?
Scanner#next is a method with side-effects. Which means that its execution changes something in the environment. However the debugger doesn't distinguish pure methods and ones with side-effects. So as soon as you've added to watches list the expression scanner.next() debugger evaluates it on every debugging step, advancing through the input, and that's what you observe.
There is no way to debug your current code while watching scanner.next(), so you should:
change the way you are debugging the code - remove scanner.next() from watched expressions.
change the code to make it possible to debug it - add a variable where intermediate parsed input will be stored.
Considering the format of your input you can create a function to tokenize the input, and then debug how each token is processed by some other function. Ideally you would like to debug a function parseRecord(String), which can be easily verified without re-inputting the data each time:
public static void main(String args[]) {
parseRecord("1,1,bugs#bunny.com,123 Sesame St.,New York,NY,10011,12345689010");
}
I'm working on a program that allows a user to read a file, search for specific text (still in progress) in a file and write (append) to a file. The program has four classes, with one method in each, corresponding to each of the functions of the program.
My first class (containing Main) prompts the user to specify whether they want to read/search/write to a default file. Like so:
public class SimpleDBFunction {
public static void main(String args[]) throws IOException{
//Prompt user to provide input in accordance with desired function
System.out.println("Type 'R' to read a file; 'S' to search for text within a file; 'W' to write to a file; 'E' to exit");
//Initialize scanner and a string variable to hold the value of scanner variable
Scanner iChoice = new Scanner(System.in); //iChoice - inputChoice
String userChoice = iChoice.next();
//If user specifies "r" go to fileReader class
if(userChoice.equalsIgnoreCase("r")){
SimpleDBReader sdbrObject = new SimpleDBReader();
sdbrObject.sdbReader(args);
//If user specifies "s" go to textSearch class
}else if(userChoice.equalsIgnoreCase("s")){
SimpleDBSearch sdbsObject = new SimpleDBSearch();
sdbsObject.sdbSearch(args);
//If user specifies "w" go to fileWriter class
}else if(userChoice.equalsIgnoreCase("w")){
SimpleDBWriter sdbwObject = new SimpleDBWriter();
sdbwObject.sdbWriter(args);
//If user specifies "e" terminate program
}else if(userChoice.equalsIgnoreCase("e")){
System.exit(0);
}
iChoice.close(); //Close scanner, probably redundant here
}
}
The specific issue I have is that I want the program to run in this "state" of awaiting user input, even after the user has already prompted the program to perform one of the actions. I have tried to use both a while loop, and a do-while loop, to achieve this; but both ended up infinitely repeating whichever function the user specifies instead of running it once and returning to main. I also tried to utilize "break" in a few different positions (foolish of me), only to find that it terminates my program completely when it is reached.
I'm still a programming green-horn, so please bear with me. I know that my code isn't the most polished thing around and that there are a multitude of ways to improve it, but what I want is full functionality before I begin improving. If you wish to see the classes pertaining to reading, searching and writing please let me know.
Put Scanner iChoice = ... on top
Put everything between that and iChoice.close(); into an infinite loop
Only the scanner init and scanner close method will be outside this loop
String userChoice = ... needs to be inside the loop as well
A proper implementation would also wrap the loop in a try block and close the scanner in finally. Also the logic to perform inside the while loop based on user input might be a candidate for a separate method, to keep the try block easy to comprehend.
I've been searching overflow questions and googling it for about half an hour and can't find an answer for this.
At first I thought it might be that I'm not closing my Scanner object. I added
inp.close();
after all my code,but still nothing.
I'm using Eclipse to create a simple Binary Search algorithm.
My problem is that it is not keeping my input. And what's even weirder is that it only accepts "5".
After pressing enter it only creates more spaces. It doesn't move on to the rest of the program.
I've also tried entering more values under the "skipped" ones without any success.
Here's some screenshots
nextInt() reads scans the next token of the input as an int.
If the input is not an int, then an InputMismatchException is thrown.
You can use next() to read the input, whatever its type is. And you can hasNextInt() to make sure the next input is an int:
Scanner inp = new Scanner(System.in);
if(inp.hasNext()) {
if(inp.hasNextInt()) {
int n = inp.nextInt();
// do something with n
} else {
String s = inp.next();
// do something with s
}
}
Actually, I have a theory - your Scanner code is working just fine, it's your binary search code that's broken. Whatever it's doing works on an input of 5 but falls into an infinite loop for other inputs.
Consider breaking up your input parsing code from your binary searching code (e.g. do input parsing in main() and define a binarySearch() function that main() calls) so that you can test them separately.