Trying to do some Command Line Arguments for a program. Next int is clearly present but Scanner throws NoSuchElement exception. With or without new line/whitespace skip, trim() on string before it, etc.
try {
String s = String.valueOf(scan.next().charAt(0));
String t = String.valueOf(scan.next().charAt(0));
if ((s+t).trim() != "-s") {
throw new IOException ("Size must be allocated with ā-sā.");
}
System.out.println("Got ''-s'' successfully.");
} catch (IOException SizeFormatIncorrect) {
}
try {
//scan.skip("(\r\n|[\n\r\u2028\u2029\u0085])?"); - with or
//without, gives same problem
size = scan.nextInt();
System.out.println("Got " + size);
} catch (NumberFormatException NotInt)
{ }
Input:
-s 200 or -s 2
OR
-s\n200 or -s\n2
Output:
Enter variables to test call:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at HelloWorld.main(HelloWorld.java:28)
//(Line 28 is size = scan.nextInt())
//If I add
if (!scan.hasNextInt()){
System.out.println("We have :" + scan.nextLine().getBytes());
}
I get output:
We have :[B#42a57993
So whoever wants to tell me and everyone else reading how to cast whatever it is Scanner thinks it's reading in to an Int. (Integer.parseInt() wouldn't work)
I properly allocated scan with Scanner scan = new Scanner(System.in)
Then Scanner reads from System.in (standard input). Not the command line. You could concatenate your arguments into a String and then use that as a source for your Scanner. Like,
Scanner scan = new Scanner(String.join(" ", args));
You will also need to change (at least)
(s+t).trim() != "-s"
because that is not a good way to compare String(s). You need something like
!(s+t).trim().equals("-s")
Related
I'm writing a program and have been having some trouble with my code. I invoke a method called secondChance() which gives users a second opportunity to enter a valid input. The method is defined as follows:
Scanner input2 = new Scanner(System.in);
StringBuilder html = new StringBuilder();
String val;
try {
System.out.println("Please enter file name you would like to view (include .csv at the end):");
String fileName = input2.nextLine(); //LINE 191
if (!(fileName.equals("doctorList.csv"))) {
input2.close();
throw new FileNotFoundException();
} else {
BufferedReader br = new BufferedReader(new FileReader(file2));
while ((val = br.readLine()) != null) {
html.append(val);
}
br.close();
input2.close();
String output = html.toString();
System.out.println(output);
}
} catch (FileNotFoundException e) {
System.out.println("Invalid file input. Terminating program.");
System.exit(0);
} catch (IOException e) {
System.out.println("Error occured. Terminating program.");
input2.close();
System.exit(0);
}
}
The output/error I get is:
Please enter file name you would like to view (include .csv at the end):
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at CSV2HTML.secondChance(CSV2HTML.java:191)
at CSV2HTML.main(CSV2HTML.java:68)
Line 68 in the exception is the line where the method is invoked. The code that is in the method for asking user input is identical to the code shown inside the secondChance() method. For reference, here is the code which invokes the secondChance() method:
} catch (FileNotFoundException e) {
System.out.println("Invalid file input. Now initiating second chance.");
secondChance(); //THIS IS LINE 68
}
EDIT: I've added input2 at the top of my code block, to show where/how it is initialized.
There are only 2 explanations for scanner.nextLine() throwing that exception. From the way you wrote the question, only one of those two is feasible here:
You have close()d System.in!
System.in is your applications standard input. Assuming you just started the app as normal, that'll be 'the keyboard', effectively, which is endless, and therefore that exception cannot ordinarily happen. If you start it with java -jar yourapp.jar <somefile.txt, you're telling the OS to use somefile.txt as 'the keyboard', and that certainly can run out of lines, and that's the other unlikely explanation. (If you're actually starting your app that way, then that's your explanation: The scanner's consumed all lines. There's probably a bug in your code which results in reading 'too many' lines, step through with a debugger).
However, you can close this resource, which means any further attempts to read from System.in will just fail exactly like you're seeing. The solution is trivial: Do not ever close System.in.
Scanner is a filter and if you close a scanner, then the scanner closes the underlying resource. Thus, assuming you have a scanner of System.in (new Scanner(System.in)), the rule "do no close System.in" expands to: "... and also never close those scanners either".
You have either written:
scanner.close();
or you have written:
try (Scanner s = new Scanner(System.in)) {
// stuff with scanner here
}
That construct invokes the close() method on the thing in the try parentheses when the code 'walks out' of the try block, regardless of how it walks out (control flow, such as a return statement, exception thrown, or just run to the end of it).
Some IDEs will notice you're using a class marked as being a resource (or even just anything that can be used in a try-with as above) and will warn you that you should use try-with. The editor / linting tool is WRONG and you must ignore it. The concept of 'which things should be closed or not' is vastly more complicated than these simplistic tools act like they are. This is one of those resources that you must in fact not close.
Just get rid of it. Delete scanner.close() / replace:
try (Scanner s = new Scanner(System.in)) {
codeHere();
}
with just:
Scanner s = new Scanner(System.in);
codeHere();
This question already has answers here:
How to use Scanner to accept only valid int as input
(6 answers)
Closed 2 years ago.
I have a separate thread class and below is the run method,
#Override
public void run() {
Scanner scanner = new Scanner(System.in);
int iRequestType = 0;
int iRequestId = 0;
while (!exit){
try {
System.out.print("\nRealTime - 1\nHttpUrl - 2\nSelect one : ");
iRequestType = scanner.nextInt(); //it will wait here after the exception occurs
System.out.print("\nEnter Request ID : ");
iRequestId = scanner.nextInt();
if(iRequestType == 1 && !map_RealTimeRequests.isEmpty()){
sendRealTimeRequest(iRequestId);
} else if (iRequestType == 2 && !map_HttpUrlRequests.isEmpty()){
sendHttpUrlRequest(iRequestId);
} else if(iRequestType > 2) {
System.out.println("Invalid List Number");
}else {
System.out.println("Empty List");
}
} catch (InputMismatchException e){
System.out.println("Invalid request type or ID : " + e);
scanner.close();
scanner = new Scanner(System.in);
}
}
}
If I enter numbers, the program works fine. When I enter a character, it goes to the catch block and and execute the lines within it as expected. Once the execution of catch block completes, it will iterate again and ask for the keyboard inputs. But when I try to enter a value (a number or a character), it does not read anything and keep waiting without executing the next lines.
What I want to do is, ask the user to enter a number and if the user enter a character, print an error message in console and iterate the while loop again. How can I solve this issue? Thanks in advance!
You should not call scanner.close() because that closes System.in. You don't want to close System.in you just want to clear out the buffer. You can do that by replacing the scanner as you did (without the close() call), or you can call nextLine() if it's single-line input like this:
} catch (InputMismatchException e){
System.out.println("Invalid request type or ID : " + e);
scanner.nextLine();
}
I'm working on a Windows 7 machine.
I'm working on an application which is a front for the GHCi interpreter for Haskell. The user will input a command, then Java will execute the command via the exec() method on Runtime, and then the application will display the text that would display if the user was just running GHCi using command prompt.
Right now, I'm running into issues with the loop that prints the output.
Here is the code I have right now.
public class GHCiTest {
public static Scanner rd, sc;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
System.out.println("Starting... ");
Process p = Runtime.getRuntime().exec("ghci");
PrintStream hugsin = new PrintStream(p.getOutputStream());
InputStream hugsout = p.getInputStream();
sc = new Scanner(hugsout);
rd = new Scanner(System.in);
String rdnextline;
while (true){
while (sc.hasNextLine()){
System.out.println(sc.nextLine());
}
System.out.println("yay");
rdnextline = rd.nextLine();
if (rdnextline == "quit"){break;}
hugsin.println(rdnextline);
hugsin.flush();
}
System.out.println(" ... successful completion.");
}
catch(IOException e) {
e.printStackTrace();
}
}
}
I know that the initial starting of GHCi is working, because the program is printing out "GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help". However, the issue appears to be the while(sc.hasNextLine()) loop, which is supposed to read the output of the command prompt and output it until there's nothing left, as it won't break out of the loop and proceed to read the user input. I know this because the program isn't printing the "yay" flag I put in after the loop.
Receive output of ghci in another thread like this.
System.out.println("Starting... ");
Process p = Runtime.getRuntime().exec("ghci");
PrintStream hugsin = new PrintStream(p.getOutputStream());
InputStream hugsout = p.getInputStream();
Scanner rd = new Scanner(System.in);
new Thread(() -> {
try (Reader r = new InputStreamReader(hugsout)) {
int ch;
while ((ch = r.read()) != -1)
System.out.print((char)ch);
} catch (IOException e ) {}
}).start();
Scanner sc = new Scanner(hugsout);
String rdnextline;
while (true) {
rdnextline = rd.nextLine();
hugsin.println(rdnextline);
hugsin.flush();
if (rdnextline.equals("quit")) {
break;
}
}
System.out.println(" ... successful completion.");
Your loop won't exit until the end of the stream has been reached:
while (sc.hasNextLine()){
System.out.println(sc.nextLine());
}
The end of the stream is the end of your process. So, your Java program is waiting for the sub process to run to completion, and terminate. Once that happens, the loop will end, and the Java program will send the desired commands to the process.
Sorry, I mean, try to send the desired commands to the process; it won't succeed because the process has terminated.
If the GHCi process outputs a "prompt" of some kind, you could try to break your while(...) { print } at that moment, get input from the user, send that to the process, and then loop back and re-enter your while(...) { print }, waiting for the next prompt.
Assuming the prompt does not end with a newline, but rather appears at the start of a line where the user input gets typed, you cannot use a while(sc.hasNextLine()) { ... } type of loop, because the prompt is not a complete line. You might have to resort to reading character by character, looking for the prompt sequence in the last "n" characters.
Looks like you can change the prompt in GHCi. See here for details. If you change the prompt to end with a newline, you could still read the stream in lines.
while (sc.hasNextLine()){
String line = sc.nextLine();
if (line.equals("YourPromptHere"))
break;
System.out.println(line);
}
(Alternately, you might be able to do something with threads to allow both parts to run without blocking each other. Of course, threading comes with its own issues and complexity.)
EDIT
I had a blinding flash of the obvious. Assuming GHC's prompt looks like this ...
GHCi, version 7.10.3
yada, yada, yada ...
Main> _
... you could set the scanner's delimiter to be the prompt string Main>.
// Set scanner delimiter to GHCi's Prompt string
sc = new Scanner(hugsout).setDelimiter("^Main> ");
while (sc.hasNext()) {
// Echo GHCi's output upto the delimiter (prompt)
System.out.println(sc.next());
// Read user input & transfer to GHCi.
System.out.print("Replacement Prompt> ");
rdnextline = rd.nextLine();
if (rdnextline == "quit") {
break;
}
hugsin.println(rdnextline);
hugsin.flush();
}
Note: This does not take into account the secondary prompt, used when GHCi expects more input to complete the command. You could use a regex something like "^Main> |\bAlt> " that matches either prompt, but you would not be able to tell which prompt the delimiter matched.
The first subexpression "^Main> " matches the start of a line, followed by "Main> ", where as the second subexpression "\bAlt> " only matches a word boundary followed by "Alt> ". This is because the output stream of the GHCi, would look like "\nMain> Alt> " with a long pause before the Alt>; the "newline" before Alt> would normally come from the echoing of the Enter keypressed on the input stream.
I have a very simple loop that waits for a number (int) and as long as that number is not exitOption it does not leave the loop, however I get an unexpected error, and I don't know what's causing it.
Edit
Adding another snippet so you can compile
public static void main(String[] args) throws FileNotFoundException,
SecurityException,
IOException,
ClassNotFoundException {
while (controller.selectOptionMM());
/Edit
public boolean selectOptionMM() throws SecurityException,
FileNotFoundException,
IOException {
int cmd = ui.getExitOption();
ui.mainMenu();
cmd = utils.readInteger(">>> "); // this is my problem, right here
// code in next snippet
while (cmd <1 || cmd > ui.getExitOption()) {
System.out.println("Invalid command!");
cmd = utils.readInteger(">>> ");
}
switch (cmd) {
case 1:
case 2:
case 3:
case 4: this.repository.close();
return true;
case 5: return false;
}
return false;
}
Here is what fails:
public int readInteger(String cmdPrompt) {
int cmd = 0;
Scanner input = new Scanner(System.in);
System.out.printf(cmdPrompt);
try {
if (input.hasNextInt())
cmd = input.nextInt(); // first time it works
// Second time it does not allow me to input anything
// catches InputMissmatchException, does not print message
// for said catch
// infinitely prints "Invalid command" from previous snippet
} catch (InputMismatchException ime) {
System.out.println("InputMismatchException: " + ime);
} catch (NoSuchElementException nsee) {
System.out.println("NoSuchElementException: " + nsee);
} catch (IllegalStateException ise) {
} finally {
input.close(); // not sure if I should test with if (input != null) THEN close
}
return cmd;
}
First time I pass trough, it reads the number no problem. Now if the number is not 5 (in this case exitOption), it passes again trough readInteger(String cmdPrompt) except this time it jumps to catch (InputMismatchException ime) (debug) except it does not print that message and just jumps to Error, input must be number and Invalid command.
Is something stuck in my input buffer, can I flush it, why is it (input buffer) stuck (with random data)???
I'll try debugging again and see what's stuck in my input buffer, if I can figure out how to see that.
The problem is in the call to input.close() - this causes the underlying input stream to be closed. When the input stream being closed is System.in, bad things happen (namely, you can't read from stdin any more). You should be OK just eliminating this line.
input.hasNextInt()
This line throws the exception if there is no Integer, so instead of it going to else block it forward to catch block. It will never go to else block if exception get caught.
I am trying to understand how to only accept numbers from the user, and I have attempted to do so using try catch blocks, but I would still get errors with it.
Scanner scan = new Scanner(System.in);
boolean bidding;
int startbid;
int bid;
bidding = true;
System.out.println("Alright folks, who wants this unit?" +
"\nHow much. How much. How much money where?" );
startbid = scan.nextInt();
try{
while(bidding){
System.out.println("$" + startbid + "! Whose going to bid higher?");
startbid =+ scan.nextInt();
}
}catch(NumberFormatException nfe){
System.out.println("Please enter a bid");
}
I am trying to understand why it is not working.
I tested it out by inputting a into the console, and I would receive an error instead of the hopeful "Please enter a bid" resolution.
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:909)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextInt(Scanner.java:2160)
at java.util.Scanner.nextInt(Scanner.java:2119)
at Auction.test.main(test.java:25)
Try catching the type of exception thrown rather than NumberFormatException (InputMismatchException).
The message is pretty clear: Scanner.nextInt() throws an InputMismatchException, but your code catches NumberFormatException. Catch the appropriate exception type.
While using Scanner.nextInt(), it causes some problems. When you use Scanner.nextInt(), it does not consume the new line (or other delimiter) itself so the next token returned will typically be an empty string. Thus, you need to follow it with a Scanner.nextLine(). You can discard the result.
It's for this reason that I suggest always using nextLine (or BufferedReader.readLine()) and doing the parsing after using Integer.parseInt(). Your code should be as follows.
Scanner scan = new Scanner(System.in);
boolean bidding;
int startbid;
int bid;
bidding = true;
System.out.print("Alright folks, who wants this unit?" +
"\nHow much. How much. How much money where?" );
try
{
startbid = Integer.parseInt(scan.nextLine());
while(bidding)
{
System.out.println("$" + startbid + "! Whose going to bid higher?");
startbid =+ Integer.parseInt(scan.nextLine());
}
}
catch(NumberFormatException nfe)
{
System.out.println("Please enter a bid");
}