Running into an error with this project I'm working on for a computer science course, and hoping someone can give me insight into what may be happening. A bit of background to what's occurring in the code:
In the below code, I have the start of my program which displays a UI menu and asks for user input and uses a switch statement to run appropriate methods based on user input.
/**
* Start of program
*/
public static void main(String[] args) {
Library library = new Library();
char userChoice; //Stores what menu item the user chose
Scanner userMenuChoiceScanner = new Scanner(System.in);
boolean loop = true;
displayMenu(); //Displays main UI menu
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0)); //Gets user's menu choice
/*Loops UI menu afer user has made menu choice and exits loop if user choses 'q' from menu.*/
while(loop) {
/* Switch descides what menu choice user has made and whether to prin menu UI again, load,
* search, print, or analyze a music catalog, or to quit program.
*/
switch(userChoice) {
case 'm':
System.out.println();
displayMenu();
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
break;
case 'p':
System.out.println();
if(library.getBooks().size() != 0) {
printLibrary(library);
} else {
System.out.println("There are no books in the library. Please add a book first.");
}
System.out.print("Please enter a command (press 'm' for Menu):");
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
break;
case 'a':
System.out.println();
addBookToLibrary(library);
System.out.print("Please enter a command (press 'm' for Menu):");
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
break;
case 'd':
System.out.println();
if(library.getBooks().size() != 0) {
deleteBookFromLibrary(library);
} else {
System.out.println("There are no books in the library. Please add a book first.");
}
System.out.print("Please enter a command (press 'm' for Menu):");
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
break;
case 'r':
System.out.println();
if(library.getBooks().size() != 0) {
readBookFromLibrary(library);
} else {
System.out.println("There are no books in the library. Please add a book first.");
}
System.out.print("Please enter a command (press 'm' for Menu):");
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
break;
case 'q':
System.out.println();
System.out.println("Thank you! Goodbye!");
loop = false;
break;
default:
System.out.println();
System.out.println("Invalid selection!");
System.out.print("Please enter a command (press 'm' for Menu):");
userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
System.out.println();
}
}
userMenuChoiceScanner.close();
}
What's occuring is when tthe user makes a choice, it goes into the appropriate methods and fulfills it's tasks there, then when it returns to the switch statement to get a new user input, it throws a java.util.NoSuchElementException error as if the scanner stream was closed, but I don't close the scanner until the end (the stream should still be open).
The switch statement is set up in a way where a book must be added (the user must chose 'a' first) before any other option can be chosen. Here is the code to he addBookToLibrary() method which has a couple scanners which are opened and closed. I assume maybe closing out these scanners may be causing the issue?
/**
* Adds new book to library
* #param library ArrayList object which holds book objects
*/
public static void addBookToLibrary(Library library) {
Scanner addBookScanner = new Scanner(System.in);
String title = "";
String author = "";
String genre = "";
String filename = "";
boolean addStatus = false;
/*Asks user for book details */
System.out.println("Enter the details of the book you want to add to the library:");
System.out.println("What is the book title?");
title = addBookScanner.nextLine();
System.out.println("What is the author's name?");
author = addBookScanner.nextLine();
System.out.println("What is book genre?");
genre = addBookScanner.nextLine();
System.out.println("What is the book's filename?");
filename = addBookScanner.nextLine();
addBookScanner.close();
Book newBook = new Book(author, title); //creates new book with author and title set
newBook.setGenre(genre); //sets book genre
File bookFile = new File(System.getProperty("user.dir") + '\\' + filename); //used to check if file user provided exists
System.out.println(bookFile);
/*Checks to see if file user provided actually exists*/
if(bookFile.exists()) {
try {
newBook.setFilename(filename);
}catch(Exception e) {
}
}
else {
Scanner getNewFilenameScanner = new Scanner(System.in);
//Continues to ask user for new filename if file doesn't exist
do {
System.out.println("I'm sorry, but the file you specified does not exist.");
System.out.print("Enter a new file name:");
bookFile = new File(getNewFilenameScanner.nextLine());
}while (!(bookFile.exists()));
getNewFilenameScanner.close();
}
addStatus = library.addBook(newBook); //adds book to library
if(addStatus) {
System.out.println("Book was successfully added!");
}
else {
System.out.println("Book was not successfully added. Please try again.");
}
}
This code worked perfectly in a previous project, so I'm not certain why it's not working now. Any help would be greatly appreciated.
Thank you so much
In your addBookToLibrary method, you close the Scanners after you are done using them. However, those scanners are connected to System.in, the standard input stream. Closing those scanners will also close the standard input stream, according to the documentation.
What else is connected to the standard input stream? userMenuChoiceScanner! After the standard input stream is closed, userMenuChoiceScanner can't read from it, hence throwing an exception.
Note that although userMenuChoiceScanner is not closed until the very end, the stream that it is reading from is closed.
In fact, you don't need to create multiple scanners here. You only need to use one scanner, and pass it around to different methods. For example, addBookToLibrary could accept a Scanner:
public static void addBookToLibrary(Library library, Scanner s) {
And it will only use s to read inputs. You can pass your userMenuChoiceScanner to it:
addBookToLibrary(library, userMenuChoiceScanner);
As a general rule, you should not close anything that is not opened by you. You didn't open the standard input stream (the JVM did), so you shouldn't close it.
Related
I'm trying to implement the main method in java for a KWIC. The issue I'm having is that I have to ask the user if they want to write the input from the console/file and write the output to the console/file. The first time asking the user for console/file works fine when I have to read, but when I ask them again for the output I believe it goes back into the first If condition. Here is the code for reference.
try {
System.out.println("Please enter FILE to input from file or CONSOLE to input from console:");
String userInput = "";
while ((userInput = scannerWrapper.nextLine()) != "-1") {
if (userInput.equals("CONSOLE")) {
System.out.println("Please enter FILE to output from file or CONSOLE to output from console:");
List<String> cshiftConsole = circularShifter.shiftLines(inputFromConsole.read());
if (userInput.equals("CONSOLE")) {
System.out.println("Please enter lines to add, then enter -1 to finish:");
// Console
cshiftConsole = alphabetizer.sort(cshiftConsole);
outputToConsole.write(cshiftConsole);
for (String element : cshiftConsole) {
System.out.println(element);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
This is my console output
Please enter FILE to input from file or CONSOLE to input from console:
CONSOLE
Please enter FILE to output from file or CONSOLE to output from console:
CONSOLE
Software Architecture
-1
Please enter lines to add, then enter -1 to finish:
Architecture Software
CONSOLE
Software Architecture
After the second CONSOLE(userInput) I should be asked to enter the lines, But this is taking CONSOLE as the input I want to circularly shift. Any help would be great thank you.
You have some issues in your code, and if I understand correctly you want to decide where to INPUT from, where to OUTPUT to and get a couple of Strings into a List.
(userInput = scannerWrapper.nextLine()) != "-1" You compare Strings in Java using .equals(...) as you did in your code further below.
Every time you're asking your user where he wants to input from, you just have to read it once, so instead of having it inside a while do it on an if.
You create your list on every iteration, have it as an instance member instead.
On every iteration you're printing your objects, wait until the user stops adding items first (they type -1)
A better approach could be like this:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class InputCycle {
private Scanner scanner;
private static final String CONSOLE = "CONSOLE";
private static final String EXIT_CODE = "-1";
private List<String> list;
public static void main(String[] args) {
new InputCycle().readAndWrite();
}
private void readAndWrite() {
scanner = new Scanner(System.in);
list = new ArrayList<String>();
System.out.println("INPUT FROM CONSOLE / FILE");
String input = scanner.nextLine(); // Read where to input from
if (input.equals(CONSOLE)) {
System.out.println("OUTPUT TO CONSOLE / FILE");
String output = scanner.nextLine(); // Read where to output to
if (output.equals(CONSOLE)) {
System.out.println("WRITE LINES (" + EXIT_CODE + " TO EXIT)");
String line = "";
do {
line = scanner.nextLine(); // Read every line
if (!line.equals(EXIT_CODE)) {
list.add(line);
}
} while (!line.equals(EXIT_CODE));
} else { // Write to a file with your own code
System.out.println("Writing to a file");
}
} else { //Read from a file
System.out.println("Reading from a file");
}
System.out.println("ALL LINES: ");
list.forEach(line -> System.out.println(line)); //Print all the lines user wrote
}
}
That has this output:
INPUT FROM CONSOLE / FILE
CONSOLE
OUTPUT TO CONSOLE / FILE
CONSOLE
WRITE LINES (-1 TO EXIT)
FOO
BAR
BANANA
-1
ALL LINES:
FOO
BAR
BANANA
I've been writing my first Java script and have ran into an issue. I do not understand why when this is ran the program waits for the user to input something on the first time the loop runs, then the input is dealt with and the corresponding response is made, but the second time it runs it gets stuck in an infinite loop without waiting for the user's input. For the record, I do want this to be an infinite loop, except that the program should end if the user enters "3". If after each case I write "keep_going = false;" the program functions, but doesn't keep looping, obviously. All help is appreciated, thanks!
import java.io.*;
class Choice
{
public static void main (String[] args)
{
String input = "";
Boolean keep_going = true;
while (keep_going)
{
input = "";
System.out.println("Welcome to my program! Would you like to:");
System.out.println("1. Say hi.");
System.out.println("2. Find out my favourite colour.");
System.out.println("3. End the program.");
System.out.println(">");
System.out.print( "> " );
InputStreamReader isr = new InputStreamReader( System.in );
BufferedReader buffer = new BufferedReader( isr );
try
{
input = buffer.readLine();
buffer.close() ;
}
catch (IOException e )
{
System.out.println(e);
}
switch (input)
{
case "1": System.out.println("Hi!"); break;
case "2": System.out.println("My favourite colour is blue!"); break;
case "3": return;
default : System.out.println(input + " is not a valid option. Please try again.");
}
}
}
}
the infinite loop was due to line buffer.close() ;
Make this adjustments
remove buffer.close() ;
//buffer.close() ;
case "3": keep_going=false;break;
I am trying to make the user input an Airport Name, and the program will search from a text file to get the matching Code, right now I only need it to read the line. I have looked into many similar questions in here, but nothing works for me. The program return the else result rather than the found result.
This is my code so far
public static void main (String[] args) throws IOException
{
File file = new File("codes01.dat");
Scanner myFile = new Scanner(file);
Scanner kb = new Scanner(System.in);
String line;
System.out.println("Hey man, this is totally leigt, just enter an Airport code and I'll hook you up.");
System.out.print("First, y'all need to give me the file name: ");
String fileName = kb.nextLine();
if (fileName.equalsIgnoreCase("codes01"))
{
System.out.print("Cool, now give me your Airport Name: ");
String AirportName = kb.nextLine();
while (myFile.hasNextLine())
{
line = myFile.nextLine();
String name = myFile.next();
System.out.println(line);
if(name.equalsIgnoreCase(AirportName))
{
System.out.println("IT'S WORKING, I DON'T KNOW HOW BUT IT IS "+line);
break;
}
else
{
System.out.println("Sorry, dude, ain't no airport in my VERY limited list with that name");
break;
}
}
}
The program return the else result rather than the found result.
That is because you are breaking out of the loop after testing the first line in your file.
Look carefully at your code ... in context.
if(name.equalsIgnoreCase(AirportName)) {
System.out.println("It is working");
break;
} else {
System.out.println("Sorry");
break; // What????
}
Why are you using the break statement in the if-else block? Try to get rid of the break statement and then execute your code.
if(name.equalsIgnoreCase(AirportName))
{
System.out.println("The name of Airport matches");
}
else
{
System.out.println("Sorry No Match Found");
}
Look closely at these two lines. There's a problem there. Step through the code in your head pretending you are the Scanner class.
line = myFile.nextLine();
String name = myFile.next();
well im currently learning java my myself but from what i know i just cant seem to fix this problem
currently testing a script where if u dont type ur name exactly u must re-type it but this error appears i searched everywhere but most of the things i tried dont work
Please type in your name:
lucas
Welcome lucas
Confirm your name:
luca
Please type in your name:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at input.main(input.java:9)
here is the code:
import java.util.Scanner;
public class input {
public static void main(String[] args) {
while (true) {
try (Scanner input = new Scanner(System.in)) {
System.out.println("Please type in your name: ");
String name = input.nextLine();
System.out.println("Welcome " + name);
if (name.equals("nico")) {
System.out.println("bitch");
break;
} else {
System.out.println("Confirm your name:");
String name1 = input.nextLine();
if (name1.equals("nico")) {
System.out.println("Hello " + name1 + "... bitch");
} else if (name1.equals(name)) {
System.out.println("Thank you");
break;
}
}
}
}
}
}
Move the try-with-resources to around your while loop. When execution leaves the try-with-resources, Java closes the resources. Here, that resource is the standard input, which cannot be re-opened.
try (Scanner input = new Scanner(System.in)) {
while (true) {
System.out.println("Please type in your name: ");
You actually don't really need the try-with-resources here. Don't close standard input/output/error.
Don't put the Scanner into your loop.
Loop while the scanner still has input.
Currently, you create new Scanner too often.
this is the code i use when opening the txt file but it overwrites the data everytime i want to put in more data.
private Formatter X;
private File Y = new File("C:\\Users\\user\\workspace\\Property Charge Management System\\users.txt");
private Scanner Z;
public String[][] PCMSarray;
public boolean OpenFile() {
try{
if(Y.exists()==false){
X = new Formatter("users.txt");
}
return true;
}
catch(Exception e){
System.out.println("File has not yet been created.");
return false;
}
}
This is the code i use to write to the file but this works.
public void WriteToFilecmd(){
Scanner input = new Scanner(System.in);
System.out.println("Please enter your First name");
String Fname = input.next();
System.out.println("Please enter your Last name");
String Lname = input.next();
System.out.println("Please enter your Password");
String Password = input.next();
System.out.println("Please enter your user ID");
String ID = input.next();
System.out.println("Please enter the first address line of your Property");
String addressln1 = input.next();
System.out.println("Please enter the second address line of your Property");
String addressln2 = input.next();
System.out.println("Please enter the third address line of your Property");
String addressln3 = input.next();
System.out.println("Please enter the properties estimated market value");
String EstimatedPropertyValue = input.next();
System.out.println("Please enter your tax owed");
String Taxowed = input.next();
input.close();
X.format("%1$20s %2$20s %3$20s %4$20s %5$20s %6$20s %7$20s %8$20s %9$20s \n",Fname,Lname,Password,ID,addressln1,addressln2,addressln3,EstimatedPropertyValue,Taxowed);
}
Use a different constructor for the Formatter, one that takes a FileWriter (which is Appendable), and construct the FileWriter so that it appends to the end of the file:
// the second boolean parameter, true, marks the file for appending
FileWriter fileWriter = new FileWriter(fileName, true);
Formatter formatter = new Formatter(fileWriter);
As an aside, please learn and follow Java naming rules, else your code will not be easily understood by others (namely us!). Variable and method names should begin with lower-case letters.
Your code is a bit of a mess in a number of respects, but I think that the problem is that you are testing:
C:\\Users\\user\\workspace\\Property Charge Management System\\users.txt
but then you are opening
users.txt
... which happens to be a different file because your "current directory" is not what you think it should be.
Even if that is not what is causing your problem, you should fix it. The way the code is currently written it will break if your current directory is not "C:\Users\user\workspace\Property Charge Management System" when the code is executed.
If you really want to append to the file instead of overwriting it, then you need to use a Formatter constructor that takes an opened output stream or writer ... and supply it with a stream that has been opened in append mode.
I should also not that you've made a serious style mistake in your code. The universal rule for Java code is that variable names and method names must start with a lower-case letter. People assume that anything that starts with an upper-case letter is a class ... unless the name is ALL_CAPITALS, which is reserved for manifest constants.