Simple java input problem - java

I'm new to java and having problems with getting input.
This is my code which seems to get the first input as required, but then skips the next two "read" function calls?
Any suggestions?
// open up standard input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int battMax, battMin, numNodes=0;
System.out.print("Enter minimum battery level:");
try {
battMin = br.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.print("Enter maximum battery level:");
try {
battMax = br.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.print("Enter number of nodes required:");
try {
numNodes = br.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

br.read() is going to read a single character. Furthermore, if you're reading from System.in it's likely to only see something when the user presses return - at which point, if you're on Windows, it will have an extra \r and \n to read (or just \n on Unix).
I suspect you'll find the values read by your second and third read() calls are \r and \n.
Furthermore, you're not actually getting the values you want to anyway - if someone enters '1' then you'll get a value of 49, as that's the Unicode value for that character.
You should use readLine() to read a line at a time (and then parse the string with Integer.parseInt(). Alternatively, you could use the Scanner class - I can't say I've ever used it myself, but it may be useful to you.
Finally, there's a lot of repetition in that code - I would suggest you refactor it by creating a utility method. For example, you might have:
public static int promptUserForInt(String prompt, int defaultValue,
BufferedReader reader)
throws IOException
{
while (true)
{
System.out.print(prompt);
try
{
String line = reader.readLine();
return Integer.parseInt(line);
}
catch (NumberFormatException e)
{
// Adjust as appropriate...
System.out.println
("Unable to parse input; please enter an integer.");
}
}
}
You can then use this very easily:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int battMax = promptUserForInt("Enter minimum battery level:");
int battMin = promptUserForInt("Enter maximum battery level:");
int numNodes = promptUserForInt("Enter number of nodes required:");
You could refactor further by taking in a Writer or BufferedWriter to display the prompt in - that way you could test it more easily.
Finally, I would suggest that you don't wrap each bit in a catch block for IOException; if you can't read the console input, I suspect you don't want to continue anyway, so you want to behave the same way whether the first input generates this exception or the second or third. Either declare that your method throws IOException, or have all three lines in the same try block, handled by the same catch block.

br.read() reads a char. Use Integer.parseInt(br.readLine()) which will read a whole line and convert it into an int.
Also, initialize all your local variables:
int battMax=0, battMin=0, numNodes=0;

If you're using java 1.5 or later, you can use the java.util.Scanner
public static getInt(String prompt){
int n = 0;
try {
System.out.print(prompt);
Scanner kb = new Scanner(System.in);
n = kb.nextInt();
}
catch(Exception ex){
ex.printStackTrace();
}
return n;
}
Sample Usage:
int battMax = getInt("Enter minimum battery level:");
int battMin = getInt("Enter maximum battery level:");
int numNodes = getInt("Enter number of nodes required:");

Related

Catch exceptions in a do-while loop?

Can someone explain and help me fix this program.
import java.util.*;
import java.io.*;
public class test {
public static void main(String[] args) {
Scanner key = new Scanner(System.in);
boolean clear;
int in = 0;
do {
clear = true;
try {
in = key.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
clear = false;
}
} while (clear == false);
String stringIn = Integer.toString(in);
String[] dec = stringIn.split("");
for (int i = 1; i < (dec.length); i++) {
System.out.print(dec[i] + " ");
}
}
}
Whenever I enter a invalid input instead of an int, my program keeps looping "Invalid" instead of giving the option to enter a new value for in.
The problem is that if the scanner fails to find an input in the correct format, it will throw an exception and not read the input.
Because the scanner does not read the invalid int input, the next time nextInt is called, it will try to read the invalid input again, and miserably fails at it, printing another "invalid!"
So you need to read the input afterwards if it finds an invalid int:
// do this in the catch block:
key.next();
This makes sure that the next token is read.
Full code:
Scanner key = new Scanner(System.in);
boolean clear;
int in = 0;
do {
clear = true;
try {
in = key.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
clear = false;
key.next();
}
} while (clear == false);
String stringIn = Integer.toString(in);
String[] dec = stringIn.split("");
for (int i = 1; i < (dec.length); i++) {
System.out.print(dec[i] + " ");
}
Check the API of the nextInt method:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched.
Meaning, that if it's not successful - it will not advance and will try to execute nextInt over the illegal token over and over again failing every time.
Try adding next() into the exception catch clause, it should skip the token and read the next one then. next() reads a String, so it does not really care about the formatting, and will allow you to advance the position in the stream to read the next token.
The problem is that you are writing to the console inside the catch, so then when you call key.nextInt() in the try the program reads the value you print to the console, so an easy way to solve this is to add a line like: key.nextLine() inside the catch and that will solve your problem.

How to correctly use try-catch-finally blocks in Java?

What would be the proper way to use the finally block to close out of the file that I was in : event.dat. If you could help me makes sense of this, I'd greatly appreciate it. I've literally spent 4 hours moving things around, playing with the code and searching for answers online, but to no avail. Code works great without that portion, but I need to know how it works for future instances. Thank you and have a good day!
I am having issues with this block:
finally{
fstream.close();
}
Which is located in the following code:
String answer;
String letter;
String inType = "";
double inAmount = 0;
double amount;
description();
GironEventClass newInput = new GironEventClass();
try{
File infile = new File("event.dat");
Scanner fstream = new Scanner(infile);
System.out.println("File Contents ");
while(fstream.hasNext())
{
inAmount = fstream.nextInt();
inType = fstream.next();
try{
newInput.donations(inType, inAmount);
}
catch(IllegalArgumentException a){
System.out.println("Just caught an illegal argument exception. ");
}
finally{
fstream.close();
}
}
System.out.println("Total Sales: " + newInput.getSale());
System.out.println("Donations: " + newInput.getDonated());
System.out.println("Expenses: " + newInput.getExpenses());
}
catch (FileNotFoundException e){
System.out.println("\nEvent.dat could not be opened. ");
}
do{
System.out.print("Are there any more items to add that were not in the text file? (Type 'Y' or 'N')");
answer = keyboard.next();
if (("Y".equals(answer)) || ("y".equals(answer)))
{
letter = inLetter();
amount = inAmount();
newInput.donations(letter, amount);
}
}while (("Y".equals(answer)) || ("y".equals(answer)));
newInput.display();
}
public static String inLetter(){
Scanner keyboard = new Scanner(System.in);
String result;
String resultTwo;
System.out.println("T = Tiket Sales");
System.out.println("D = Donations");
System.out.println("E = Expenses");
System.out.print("Please input an identifier ");
result = keyboard.nextLine();
resultTwo = result.toUpperCase();
return resultTwo;
}
public static double inAmount(){
Scanner keyboard = new Scanner(System.in);
double result;
System.out.println("Please input an amount ");
result = keyboard.nextInt();
if(result <= 0.0){
System.out.print("Please input a positive and non-zero amount ");
result = keyboard.nextInt();
}
return result;
}
public static void description(){
System.out.println("The program will ask you what amount is being spent on what.");
System.out.println(" ex: expenses, ticket sales, and profts.");
System.out.println("This program will help determine whether the event generated or lost money.");
}
This is how the scanner should work:
while scanner has object
read them ( one object per method's call)
when objects are done
close the reader.
Your problem is that you use the close function when the while conclusion is true. So you should put it outside of the while loop
The Try block attempts to do something.
The Catch block only executes if something went wrong during the Try block.
The Finally block executes after the Try block (and Catch block, if executed) EVERY time.
Your issue is that you attempt to close the fstream inside the while loop.
while(fstream.hasNext()) <----- referencing fstream
{
inAmount = fstream.nextInt();
inType = fstream.next();
try{
newInput.donations(inType, inAmount);
}
catch(IllegalArgumentException a){
System.out.println("Just caught an illegal argument exception. ");
}
finally{
fstream.close(); <---- closing said stream
}
}
Since you've closed the stream, this while loop should only ever execute once. That being said, close the fstream outside the while loop and your program should return to normal.
You can also move the while loop inside the try block, which would work as well.
You need to declare fstream outside the try block otherwise it will be not visible in the finally block.
File infile = null;
File infile = null;
try {
infile = new File("event.dat");
fstream = new Scanner(infile);
...
} catch ( ) {
...
} finally {
// You need to handle exceptions also here
infile.close();
fstream.close();
}
You can also use the new try with resources syntax and leave to the jvm the closure of your streams.

Java reprompt for user input with try... catch

So if a user puts in a postfix value like say 453-* , my method EvalPostFix() does the work, but when the user inputs something invalid like 43*+ or any invalid string want the program to repromt the user for input dont know how to implement with try catch..
'
String in;
while(true){
System.out.println("Please enter the numbers first followed by the operators, make sure to have one less operator than of numbers");
try {
in = getString();
int result = EvalPostFix(in);
System.out.println(result);
} catch (IOException e) {
// TODO Auto-generated catch block
String s = "Not a valid postfix string";
e.toString();
in = getString();
}
}
'
Looking at your code I think you just need to get rid of the in = getString(); in the catch block and add an break at the end of the try block.
I don't recommend using a while(true) or an IOException for what you are doing though, but that should get your code working.
Use a flag:
boolean flag = false;
while(!flag)
{
//make the loop break, if no exception caught
flag = true;
try{
}
catch{
//make the loop repeat
flag = false;
}
}
this should repeat the prompt every time you catch an exception. you can also use this to validate input.
how the flag is oriented depends on your preference. I like to flag true when an error occured ;)
this will also break your while loop, as soon as you get a valid input.
Something like this is can be used to get an input of desired specifications
public static void userMove() {
System.out.println("Where would you like to move? (R, L, U, D)\n");
Scanner input = new Scanner(System.in) ;
while (true){
String userInput = input.next() ;
if(userInput.length()>1){
System.out.println("Please input a valid direction");
}else{
break ;
}
}
}

How to know offset of a begining of a line in text file in java?

I want to know the offset of every line present in a text file.
For now I have tried,
path=FileSystems.getDefault().getPath(".",filename);
br=Files.newBufferedReader(path_doc_title_index_path, Charset.defaultCharset());
int offset=0; //offset of first line.
String strline=br.readline();
offset+=strline.length()+1; //offset of second line
In this way I can loop through entire file to know offset of begining of lines in entire text file. But if I use RandomAccessFile to seek through file and access a line using offset calulated by above method then I found myself in the middle of some line. That is it seems that offset are not correct.
What's wrong? Is this method incorrect to calculate offset? Any better and fast methods please?
Your code will only work for ASCII encoded text. Since some characters need more than one byte, you have to change following line
offset += strline.length() + 1;
to
offset += strline.getBytes(Charset.defaultCharset()).length + 1;
As stated in my comments below your question, you have to specifiy the correct encoding of your file. E.g. Charset.forName("UTF-8") here and also where you initialize your BufferedReader.
Apparently, this gives me the expected result. In the following program I print out each line of a file through a set of offsets that I collect through the BufferedReader. Is this your case?
public static void main(String[] args) {
File readFile = new File("/your/file/here");
BufferedReader reader = null;
try
{
reader = new BufferedReader( new FileReader(readFile) );
}
catch (IOException ioe)
{
System.err.println("Error: " + ioe.getMessage());
}
List<Integer> offsets=new ArrayList<Integer>(); //offset of first line.
String strline;
try {
strline = reader.readLine();
while(strline!=null){
offsets.add(strline.length()+System.getProperty("line.separator").length()); //offset of second line
strline = reader.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
RandomAccessFile raf = new RandomAccessFile(readFile, "rw");
for(Integer offset : offsets){
try {
raf.seek(offset);
System.out.println(raf.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Building a Scanner with an embedded FileReader recursively in java

public static Scanner getFileScanner()
{
try{
Scanner input = new Scanner(System.in);
String file = input.nextLine();
Scanner fs = new Scanner(new FileReader(file));
}catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
getFileScanner();
}finally{
return fs;
}
}
I keep getting the error that the variable fs isn't found. I can't figure out why for the life of me.
Your fs is declared under try block... to fix this, declare it outside the block:-
Scanner fs = null;
try {
...
fs = new Scanner(new FileReader(file));
}
catch (FileNotFoundException fe) {
...
}
finally {
return fs;
}
Variables declared inside a try block are not in scope inside the corresponding finally block. There are a number of issues with your approach in general... it's generally not a good idea to return inside a finally block, for example.
Here's what I'd do:
public static Scanner getFileScanner() {
Scanner input = new Scanner(System.in);
File file = null;
while (true) {
file = new File(input.nextLine());
if (file.exists() && file.isFile())
break;
System.out.println("Invalid filename. Try another:");
}
return new Scanner(new FileReader(file));
}
Lets start by listing the problems in your code:
The compilation error on the return statement is caused by fs being out of scope as described in other answers.
When you make the recursive call to getFileScanner(), you don't assign or return the result. So it won't make it back to the caller.
Using a return in a finally block is a bad idea. It will squash (throw away) any other exceptions that might be propagating at that point; e.g. exceptions that don't match a catch or exceptions thrown in a catch block.
The input.nextLine() call will throw an exception if the underlying stream has reached the EOF; e.g. the user typed [CONTROL]+D or whatever. You don't have to catch it (it is unchecked), but the return in the finally block squashes it (probably) resulting in the caller getting a null instead. Ughh ...
Hard-wiring System.in and System.out makes your method less reusable. (OK, this may not be an issue you should address in this particular case. And I won't, below ...)
In theory, your method could be made to throw a StackOverflowError; e.g. if the user hits [ENTER] a number of times. This problem is inherent in your recursive solution, and is a good reason not to do it that way.
Finally, here's a version of the method that addresses these problems:
public static Scanner getFileScanner() throws NoSuchElementException
{
Scanner input = new Scanner(System.in);
while (true) {
String file = input.nextLine();
try {
return new Scanner(new FileReader(file));
} catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
}
}
}
Note that I've replaced the recursion, gotten rid of the finally, and declared the exception that is thrown. (One could catch that exception and either report it, or rethrow it as an application specific exception.)
You declared fs in the try block and try to access it in a different scope (the finally block). The usual paradigms is to declare fs before the try block as null.
Declare it first:
public static Scanner getFileScanner() {
Scanner input = new Scanner(System.in);
Scanner fs = null;
while(fs == null) {
try{
String file = input.nextLine();
Scanner fs = new Scanner(new File(file));
}catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
}
}
return fs;
}
Just to expand on what the other guys indicated with their code samples...
Because you declare the fs variable within the try block the variable will only be scoped (visible) within the braces immediately after the try keyword.
By moving the fs variable declaration out of the try block and into the getFileScanner method body you are ensuring that the variable can be accessed by all blocks within the method body (try, catch and finally blocks).
Hope that helps!

Categories

Resources