Is a scan line escaping? - java

I've been doing a small project for class, it runs perfectly without problems but when pitted against the class's auto testers it gives back 2 No line found errors. Asking the course's staff they say it's probably because I'm trying to scan a line when none exist, but I tried printing all my scans and didn't discover anything like that.
That's all the scans I have in my code:
Scanner sc = new Scanner(System.in);
String sentence;
int choice;
System.out.println("Please enter a sentence:");
sentence = sc.nextLine();
printMenu(); // calls a function to print the menu.
// gets the require action
System.out.println("Choose option to execute:");
choice = sc.nextInt();
sc.nextLine();
(I tried with and without the last sc.nextLine)
static void replaceStr(String str)
{
String oldWord, newWord;
Scanner in = new Scanner(System.in);
// get the strings
System.out.println("String to replace: ");
oldWord = in.nextLine();
System.out.println("New String: ");
newWord = in.nextLine();
// replace
str = str.replace(oldWord, newWord);
System.out.println("The result is: " + str);
in.close();
}
static void removeNextChars(String str)
{
Scanner in = new Scanner(System.in);
String remStr; // to store the string to replace
String tmpStr = ""; //the string we are going to change.
int i; // to store the location of indexStr
// gets the index
System.out.println("Enter a string: ");
remStr = in.nextLine();
i=str.indexOf(remStr);
in.close(); // bye bye
if (i < 0)
{
System.out.println("The result is: "+str);
return;
}
// Build the new string without the unwanted chars.
/* code that builds new string */
str = tmpStr;
System.out.println("The result is: "+str);
}
Any idea how a line can leak here?

Here is the problem. You are using in.close(); at multiple places(last statement in replaceStr method and around the middle in removeNextChars method). When you close the scnaner using close() method, it closes your InputStream (System.in) as well. That InputStream can't be reopened with-in your program.
public void close() throws IOException --> Closes this input stream and releases any system resources associated with this stream. The general contract of close is that it closes the input stream. A closed stream cannot perform input operations and **cannot be reopened.**
Any read attempts after the scanner close will result into exception NoSuchElementException.
Please close your scanner only once, when your program is done.
EDIT: Scanner Closing/usage:
In yout main function:
Scanner sc = new Scanner(System.in);
....
.....
replaceStr(Scanner sc, String str);
.....
....
removeNextChars(Scanner sc ,String str);
....
....
//In the end
sc.close();
static void replaceStr(Scanner in, String str){
//All the code without scanner instantiation and closing
...
}
static void removeNextChars(Scanner in, String str){
//All the code without scanner instantiation and closing
...
}
You should be all good.

Related

Scanner Exception error?

The error should not have occurred as I have closed the Scanner object I declared in the registerN() function and declared a new one for setInfo() to use. But still, I kept getting the following output every time I input "register" as the value of option.
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at Student.setInfo(student.java:37)
at Group.registerN(student.java:87)
at Manage.main(student.java:168)
This is the code,
import java.util.*;
import java.io.File;
import java.io.PrintWriter;
// **** Student details ****//
class Student {
// Identity description
String name;
char sex;
int age;
String id;
// Educational description
String department;
void setInfo(){
Scanner input = new Scanner(System.in);
System.out.println("Please input the following information about the student...");
System.out.print("Name:\t");
name = input.nextLine();
System.out.print("Sex:\t");
sex = Character.toLowerCase(input.next().charAt(0));
System.out.print("Age:\t");
age = input.nextInt();
System.out.print("Department:\t");
department = input.nextLine();
System.out.print("ID:\t");
id = input.nextLine();
input.close();
}
}
// **** **** **** **** **** **** //
// **** Collection of the students **** //
class Group {
ArrayList<Student> DB = new ArrayList<Student>();
Student temp = new Student();
void registerN(){
Scanner input = new Scanner(System.in);
System.out.print("How many students would you like to register: ");
int n = input.nextInt();
input.close();
for(int i = 1; i <= n; ++i){
temp.setInfo();
DB.add(temp);
System.out.println("Student(s) " + i + " out of " + n + " registered.");
}
}
}
//**** **** **** **** **** **** //
// **** A class to make use of the objects **** //
class Manage {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
Group base = new Group();
// option string
String option = "";
// I specify the options a user can input here
while(true){
System.out.print("option: ");
option = input.nextLine();
option = option.toLowerCase();
if(option.equals("register")){
base.registerN();
}
else
System.out.println("\t\"" + option + "\" not recognized!\n\tReview options list.");
}
input.close();
}
}
I put a breaking point at the point control is passed to the function base.registerN(); which in turn passes control to temp.setInfo(). But immediately after that happens and setInfo() prints out Please input the following information about the student...
Name:, I get the error I put above. Why is that?
Below method you have closed input stream by calling input.close();
void registerN(){
Scanner input = new Scanner(System.in);
System.out.print("How many students would you like to register: ");
int n = input.nextInt();
input.close();
If you call the method input.close() ,System.in will be closed. It wont accept any further input.
If you want to avoid this, create a global variable of scanner which can be used by all classes
System.in. was not instantiated by by your code, but by the JVM.
JVM will take care of closing it if needed.
When you dispose of a Scanner by calling close() you can no longer read from its input stream, even if you construct a new Scanner around it. That is why closing the Scanner inside registerN method leads to an error inside setInfo method.
You should change the approach by passing one Scanner object around your code, rather than constructing one "on demand" inside setInfo method:
void setInfo(Scanner input){
...
name = input.nextLine();
...
}
Also pass Scanner to registerN:
if(option.equals("register")){
base.registerN(input);
}
This way you would use a single Scanner created in main, and never close it.

Searching for string in file and returning that specific line

I am working on student registration system. I have a text file with studentname, studentnumber and the student's grade stored in every line such as:
name1,1234,7
name2,2345,8
name3,3456,3
name4,4567,10
name5,5678,6
How can I search a name and then return the whole sentence? It does not get any matches when looking for the name.
my current code look like this:
public static void retrieveUserInfo()
{
System.out.println("Please enter username"); //Enter the username you want to look for
String inputUsername = userInput.nextLine();
final Scanner scanner = new Scanner("file.txt");
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
if(lineFromFile.contains(inputUsername)) {
// a match!
System.out.println("I found " +inputUsername+ " in file " ); // this should return the whole line, so the name, student number and grade
break;
}
else System.out.println("Nothing here");
}
The problem is with Scanner(String) constructor as it:
public Scanner(java.lang.String source)
Constructs a new Scanner that produces values scanned from the
specified string.
Parameters: source - A string to scan
it does not know anything about files, just about strings. So, the only line that this Scanner instance can give you (via nextLine() call) is file.txt.
Simple test would be:
Scanner scanner = new Scanner("any test string");
assertEquals("any test string", scanner.nextLine());
You should use other constructor of Scanner class such as:
Scanner(InputStream)
Scanner(File)
Scanner(Path)
You already have the variable that holds the whole line. Just print it like this:
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
if(lineFromFile.contains(inputUsername)) {
// a match!
System.out.println("I found " +lineFromFile+ " in file " );
break;
}
else System.out.println("Nothing here");
}

Creating mad-lib game in java and receiving NoSuchElementException method [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to create a java program that recieves a .txt file and plays the game, then prints it all into a new file (named by the user). I've reached the point where all the words have been chosen but am getting a NoSuchElementException message after that. I have a pretty basic knowledge of java and absolutely no clue how to proceed. Anyone have suggestions?
import java.io.*;
import java.util.*;
public class MadLibs {
public static void main(String[] args) throws FileNotFoundException {
Scanner console = new Scanner(System.in);
intro();
//in order to create the output file first prompts user to decide
//whether they want to create a mad-lib, view their mad-lib or quit
//if 'c' is selected then while loop is exited
String action = "c";
String fileName = "fileName";
while (action.equals("c")) {
System.out.print("(C)reate mad-lib, (V)iew mad-lib, (Q)uit? ");
action = console.nextLine();
action = action.toLowerCase();
File file = new File(fileName);
System.out.print("Input file name: ");
while (!file.exists()) {
fileName = console.nextLine();
file = new File(fileName);
if (!file.exists()) {
System.out.print("File not found. Try again: ");
}
}
//asks for a file to read from for the mad-lib game
//and creates file (named by user) to input the information
System.out.print("Output file name: ");
String outputName = console.nextLine();
System.out.println();
File outputFile = new File(outputName);
PrintStream output = new PrintStream(outputFile);
Scanner tokens = new Scanner(file);
while (tokens.hasNext()) {
String token = tokens.next();
//calls the returned placeHolder
String placeHolder = placeHolder(console, tokens, token);
String newWord = madLib(console, token, placeHolder);
//copies each token and pastes into new output file
}
}
while (action.equals("v")) {
System.out.print("Input file name: ");
fileName = console.nextLine();
File outputFile = new File(fileName);
if (!outputFile.exists()) {
System.out.print("File not found. Try again: ");
fileName = console.nextLine();
} else {
PrintStream output = new PrintStream(outputFile);
output = System.out;
}
}
while (action.equals("q")) {
}
}
public static String madLib(Scanner console, String token, String
placeHolder) throws FileNotFoundException{
String word = placeHolder.replace("<", "").replace(">", ": ").replace("-",
" ");
String startsWith = String.valueOf(word.charAt(0));
if (startsWith.equalsIgnoreCase("a") || startsWith.equalsIgnoreCase("e")
||
startsWith.equalsIgnoreCase("i") || startsWith.equalsIgnoreCase("o")
||
startsWith.equalsIgnoreCase("u")) {
String article = "an ";
System.out.print("Please type " + article + word);
String newWord = console.next();
return newWord;
} else {
String article = "a ";
System.out.print("Please type " + article + word);
String newWord = console.next();
return newWord;
}
}
public static String placeHolder(Scanner console, Scanner tokens, String
token) throws FileNotFoundException {
while(!(token.startsWith("<") && token.endsWith(">"))) {
//not a placeholder!
//continue reading file
token = tokens.next();
}
//outside of this while loop = found a placeholder!!
String placeHolder = token;
//returns placeholder to main
return placeHolder;
}
//method prints out the introduction to the game
public static void intro() {
System.out.println("Welcome to the game of Mad Libs");
System.out.println("I will ask you to provide various words");
System.out.println("and phrases to fill in a story.");
System.out.println("The result will be written to an output file.");
System.out.println();
}
}
Also am currently using a file called simple.txt with the text:
I wannabe a <job> when I grow up.
Just like my dad.
Life is <adjective> like that!
This is the full error message:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at MadLibs.placeHolder(MadLibs.java:96)
at MadLibs.main(MadLibs.java:46)
I ran your code and got a NoSuchElementException instead of a NoSuchFileException. To circumvent this exception you need to check if there are any more tokens while in the method placeHolder. Otherwise, after entering every placeholder you would still search for the next placeholder token although there is no next().
Change your code to:
while(tokens.hasNext() && !(token.startsWith("<") && token.endsWith(">"))) {
//not a placeholder!
//continue reading file
System.out.println(token);
token = tokens.next();
}

JUnit test a method that asks for user input

I have to test someone elses method that runs endlessly but asks for an input:
public void automatize()
{
String cadena = new String();
while(true)
{
System.out.println("Executing...(Enter command)");
System.out.println("Enter Q to exit");
Scanner sc= new Scanner(new InputStreamReader(System.in));
cadena=sc.nextLine();
if(cadena.toLowerCase().equals("q"))
break;
String[] command = str.split(" ");
if(comando.length!=0)
new Extractor().run(command);
}
}
How am I supposed to test this with JUnit?
This is what I've tried to do, but, well, It doesn't actually do anything:
#Test
public void testAutomatize_q() {
ByteArrayInputStream in = new ByteArrayInputStream("Q".getBytes());
System.setIn(in);
extractor.automatize();
System.setIn(System.in);
}
You can replace System.in with you own stream by calling System.setIn(InputStream in). Input stream can be byte array:
ByteArrayInputStream in = new ByteArrayInputStream("My string".getBytes());
System.setIn(in);
// do your thing
// optionally, reset System.in to its original
System.setIn(System.in)
Different approach can be make this method more testable by passing IN and OUT as parameters:
public static int testUserInput(InputStream in,PrintStream out) {
Scanner keyboard = new Scanner(in);
out.println("Give a number between 1 and 10");
int input = keyboard.nextInt();
while (input < 1 || input > 10) {
out.println("Wrong number, try again.");
input = keyboard.nextInt();
}
return input;
}
Taken from here: JUnit testing with simulated user input
You could use a framework like Mockito in order to mock the Scanner object, and return a fix value when sc.nextLine() is called.
Here's a link of mockito http://mockito.org/, see the 'how' menu to have some examples.

Why is my String not outputting my value correctly?

I Have a simple program where I just prompt to enter an item and the while loop will continue to ask until I enter the word "end" then it will end the program. When I enter a word like so:
it looks fine, But when I enter 2 words for an item as such I get this output:
notice how when i entered "green yellow" It prompted me after that to enter an item twice?
I can't figure out why it is doing so?
import java.util.Scanner;
public class ToDoListapp {
public static void main(String[] args) /*throws IOException*/ {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
System.out.println("Welome to your TodoList");
boolean keepAdd = true;
String item;
//file
//PrintWriter writeFile = new PrintWriter("TodoList.txt", "UTF-8");
// File file = new File("ToDo.txt");
// BufferedWriter writeTo = new BufferedWriter(new FileWriter(file));
while (keepAdd)
{
System.out.println("Enter an item: ");
item = sc.next();
if (item.equals("end"))
{
keepAdd = false;
}
// writeTo.write(item + "\n");
}
//writeTo.close();
}
}
The default behavior of Scanner is to use whitespace as a delimiter which will be used to break input into tokens. If you just want to use the newline character as a delimiter, try to set the delimiter explicitly.
Scanner sc = new Scanner(System.in);
sc.useDelimiter(System.getProperty("line.separator"));
System.out.println("Welome to your TodoList");
boolean keepAdd = true;
String item;
// The rest of your code
see http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html.
By default it uses any whitespace as the delimiter. So, the call to sc.next() already has its answer with the input green yellow.

Categories