Scanner.hasNext() Causing Input to be Needed Twice - java

I am working on some homework and have encountered a problem. The program creates a Tree, outputs pre/in/postorder traversals, then saves them to multiple files. The problem I'm having is getting the input. When you type in the input, after you're done typing in what should be the values of different Nodes, you may either type "done" or "exit". "Done" continues the program with the given input, while "exit" just closes the program. The weird thing is, you don't need to type the values of the Nodes twice to create those Nodes later on in the code, but you do have to type "done" or "exit" twice to get the program to listen to you. The code in question is here:
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(scanner.hasNext() && !response.equals("exit") && !response.equals("done")) {
fileWriter.write(response + " ");
response = scanner.next();
}
I have found that removing scanner.hasNext() gets it to function properly, but then it takes away sensing the EOF which is necessary for this assignment.
Here are the full three classes used in the program:
P0:
/**
* Sources for this class:
* https://www.w3schools.com/java/java_regex.asp
* https://stackoverflow.com/questions/14353947/how-to-represent-a-single-space-character-in-a-square-bracket-group
* https://upload.wikimedia.org/wikipedia/commons/1/1b/ASCII-Table-wide.svg
*
* Sources for shell script and makefile:
* https://www.cyberciti.biz/faq/run-execute-sh-shell-script/
* https://www.dummies.com/article/technology/computers/operating-systems/linux/linux-how-to-run-make-150284/
* https://www.cs.swarthmore.edu/~newhall/unixhelp/javamakefiles.html
*/
package mikefitzgibbon.p0;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class P0{
public static void main(String args[]) {
File file = new File("file");
String input = "";
//there can only be one or 0 arguments in the command line operation
if(args.length > 1) {
System.out.println("Please only enter the name of 1 file.");
System.exit(1);
}
//if a filename is specified, try getting the input from it
else if(args.length == 1){
file = new File(args[0]);
}
//else read from System.in
else {
Scanner scanner = new Scanner(System.in);
String response;
file = new File("input");
try (FileWriter fileWriter = new FileWriter(file)) {
System.out.println("Please enter strings to put into the tree.");
System.out.println("Type \"done\" to end taking in input, and type \"exit\" to prematurely quit.");
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(scanner.hasNext() && !response.equals("exit") && !response.equals("done")) {
fileWriter.write(response + " ");
response = scanner.next();
}
//exits the program with OK return value
if(response.equals("exit")) {
System.out.println("Prematurely ending program now.");
System.exit(0);
}
}
catch(IOException e){
System.out.println("Had trouble writing to file from System.in.");
}
}
//scans file for strings until there are no more data or eof is reached
try(Scanner scanner = new Scanner(file)){
while(scanner.hasNextLine()){
input += scanner.nextLine() + " ";
}
scanner.close();
}
//exit the program is file name is invalid
catch(FileNotFoundException e){
System.out.println("The file name you entered does not exist.");
System.exit(2);
}
//checks input for characters outside of the appropriate ASCII range
for(char c : input.toCharArray()){
if(!Character.isLetterOrDigit(c) &! Character.isWhitespace(c)) {
System.out.println("Your file or console input was not readable."
+ "\nPlease only use alhpanumeric characters.");
System.exit(3);
}
}
//this is only used as a reference for the filename
if(file.getName().equals("input"))
file = new File("output");
//creates the tree from the input and then converts it to the output
Tree tree = new Tree(input);
//displays the input
System.out.println("Here is your input for the program.");
System.out.println(input);
System.out.println();
//writes to the files
System.out.println("Outputting data to files " +
file.getName() + ".preorder, " +
file.getName() + ".inorder, and " +
file.getName() + ".postorder.");
System.out.println();
System.out.println("Output for " + file +".preorder: ");
tree.printPreorder(file.getName());
System.out.println();
System.out.println("Output for " + file +".inorder: ");
tree.printInorder(file.getName());
System.out.println();
System.out.println("Output for " + file +".postorder: ");
tree.printPostorder(file.getName());
System.out.println();
System.out.println("Ending program now.");
}
}
Tree:
/**
* Sources for this class:
* https://www.w3schools.com/java/java_files_create.asp
* https://www.softwaretestinghelp.com/binary-search-tree-in-java/
* https://www.youtube.com/watch?v=WLvU5EQVZqY&ab_channel=TECHDOSE
*/
package mikefitzgibbon.p0;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class Tree {
//nodes that make up this part of the tree
Node root;
//constructor calls the buildTree() function
public Tree(String input){
buildTree(input);
}
//takes a list of strings and a root node and creates the tree structure recursively using the addNode helper function
private void buildTree(String input) {
Scanner scanner = new Scanner(input);
//recursively builds tree with each word
while(scanner.hasNext()){
root = addNode(root,scanner.next());
}
}
private Node addNode(Node root, String value){
//checks root for null and sets it if it is
if(root == null){
root = new Node(value);
return root;
}
//compares the first letter of the input to the root's value and recursively traverses tere
else if(root.getValue().charAt(0) > value.charAt(0))
root.setLeftNode(addNode(root.getLeftNode(),value));
else if(root.getValue().charAt(0) == value.charAt(0))
root.setMiddleNode(addNode(root.getMiddleNode(),value));
else if(root.getValue().charAt(0) < value.charAt(0))
root.setRightNode(addNode(root.getRightNode(),value));
//return root if all else fails
return root;
}
//prints the tree printPreorder recursively
public void printPreorder(String filename){
try(FileWriter myWriter = new FileWriter(filename + ".preorder")) {
printPreorder(myWriter, root, 0);
myWriter.close();
System.out.println();
System.out.println("Successfully wrote to the preorder file.");
}
catch (IOException e) {
System.out.println("An error occurred while writing to the preorder file.");
}
}
//helper function for printPreorder()
private void printPreorder(FileWriter fileWriter, Node root,int depth) {
//base case
if(root == null)
return;
//write to file and recursive cases
try{
String indent = "";
for(int a = 0 ; a < depth ; a++){
indent += " ";
}
fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
System.out.println(indent + root.getValue().charAt(0) + ":" + root.getValue());
}
catch(IOException e){
System.out.println("Something went wrong while writing to the .preorder file.");
System.exit(4);
}
depth++;
printPreorder(fileWriter, root.getLeftNode(), depth);
printPreorder(fileWriter, root.getMiddleNode(), depth);
printPreorder(fileWriter, root.getRightNode(), depth);
}
//prints the tree printInorder recursively
public void printInorder(String filename){
try(FileWriter myWriter = new FileWriter(filename + ".inorder")) {
printInorder(myWriter, root, 0);
myWriter.close();
System.out.println();
System.out.println("Successfully wrote to the inorder file.");
}
catch (IOException e) {
System.out.println("An error occurred while writing to the inorder file.");
}
}
//helper function for printInorder()
private void printInorder(FileWriter fileWriter, Node root,int depth) {
//base case
if(root == null)
return;
//write to file and recursive cases
int previousDepth = depth;
depth++;
printInorder(fileWriter, root.getLeftNode(), depth);
try{
String indent = "";
for(int a = 0 ; a < previousDepth ; a++){
indent += " ";
}
fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
System.out.print(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
}
catch(IOException e){
System.out.println("Something went wrong while writing to the .preorder file.");
System.exit(4);
}
printInorder(fileWriter, root.getMiddleNode(), depth);
printInorder(fileWriter, root.getRightNode(), depth);
depth++;
}
//prints the tree printPostorder recursively
public void printPostorder(String filename){
try(FileWriter myWriter = new FileWriter(filename + ".postorder")) {
printPostorder(myWriter, root, 0);
myWriter.close();
System.out.println();
System.out.println("Successfully wrote to the postorder file.");
}
catch (IOException e) {
System.out.println("An error occurred while writing to the postorder file.");
}
}
//helper function for printPostorder()
private void printPostorder(FileWriter fileWriter, Node root,int depth) {
//base case
if(root == null)
return;
//write to file and recursive cases
int previousDepth = depth;
depth++;
printPostorder(fileWriter, root.getLeftNode(), depth);
printPostorder(fileWriter, root.getMiddleNode(), depth);
printPostorder(fileWriter, root.getRightNode(), depth);
try{
String indent = "";
for(int a = 0 ; a < previousDepth ; a++){
indent += " ";
}
fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
System.out.print(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
}
catch(IOException e){
System.out.println("Something went wrong while writing to the .postorder file.");
System.exit(4);
}
}
//getter and setter
public void setRoot(Node node) {
root = node;
}
public Node getRoot() {
return root;
}
}
Node:
/**
* Sources for this class:
* https://www.softwaretestinghelp.com/binary-search-tree-in-java/
*/
package mikefitzgibbon.p0;
public class Node {
//this is how the tree branches out, 3 children per node
Node left, middle, right;
String value = "";
public Node(String val) {
value=val;
}
//getters and setters
public void setRightNode(Node node) {
right=node;
}
public void setLeftNode(Node node) {
left=node;
}
public void setMiddleNode(Node node) {
middle=node;
}
public Node getRightNode() {
return right;
}
public Node getLeftNode() {
return left;
}
public Node getMiddleNode() {
return middle;
}
public String getValue() {
return value;
}
}

scanner.hasNext() will block (freeze the thread) until user input happens. You might think "No, it would return false, as currently there is no token available - there is no 'next'", but that's not how it works. There indeed may not currently be a next. But who knows what happens from here on out? Perhaps the user types CTRL+C, closing the pipe, thus, hasNext() will now return false, as there will never be a next token. Or, the user types something, and it will then return true, as now clearly there is a next token to be had. That's why it blocks: It cannot give a certain answer until you do something.
This may make no sense - keep in mind that 'standard input' is not the keyboard. It's... whatever stream is hooked up to standard input. By default that is a keyboard, but run your app with java -jar whatever.jar <somefile.txt and now it's that file. Which has a limited size. hasNext() would start returning false once you get to the 'end of the file'. You cannot normally ever get to the 'end of the keyboard', but the abstraction isn't designed solely for keyboards.
In other words, your code:
response = scanner.next();
while(scanner.hasNext() && ....
Will:
Read a token from standard input.
Will... read a token from standard input AGAIN (because hasNext() does that. If it works out, it returns true. If it turns out there is no token now nor will there ever be, it returns false).
This explain why you have to enter input twice. The solution is to remove the hasNext call there. Move it INTO the while loop. Instead of response = scanner.next() inside the loop, do something like:
if (!scanner.hasNext()) return; // or break, or System.exit(0), or whatever you want.
response = scanner.next();
}

I found that putting the scanner.hasNext() at the end of the expression fixed the problem, but I'm not entirely sure how. Here is the updated code:
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(!response.equals("exit") && !response.equals("done") && scanner.hasNext()) {
fileWriter.write(response + " ");
response = scanner.next();
}

Related

I cannot figure out why my while loop is looping two times instead of just once

Fairly straight forward question. I am trying to get this while loop to iterate only 1 time, to display either chute or ladder. But upon execution it runs through the loop two times. EDIT: I have also have a for loop implemented beforehand and with the same results.
public static String writeLogFile(String filename, int[] gameBoard) {
File fileStream = null;
PrintWriter outputFile = null;
String logFileName = null;
int i = 0;
try {
logFileName = filename.replace(".", "_log.");
fileStream = new File(logFileName);
outputFile = new PrintWriter(fileStream);
while(gameBoard.length > i) {
if(gameBoard[i] > 0) {
System.out.println("Ladder at square " + i);
}
else if(gameBoard[i] < 0) {
System.out.println("Chute at square " + i);
}
++i;
}
}
catch(FileNotFoundException b) {
logFileName = "null";
System.out.println("ERROR! Cannot create log file.");
}
outputFile.close();
return logFileName;
If the length of gameBoard is more than 1, the while-loop is going to continue to execute until it's complete. If you only want it to execute once when finding a ladder or schute then you need to break.
while(gameBoard.length > i) {
if(gameBoard[i] > 0) {
System.out.println("Ladder at square " + i);
break;
} else if(gameBoard[i] < 0) {
System.out.println("Chute at square " + i);
break;
}
++i;
}
It seems that you call the method writeLogFile() twice, because the method itself iterates one once over the complete gameBoard array.
I have instruction to determine if that method returns an exception, and used it in an if switch in the main method. Thank you so much. Now just how to figure out to determine if this method throws an exception.
Then maybe you should not catch the FileNotFoundException within your method, but instead declare it as thrown exception:
public static String writeLogFile(String filename, int[] gameBoard) throws FileNotFoundException {
// ...
}
Then you can catch the exception in your main method.

Searching a red black tree through text file

I am working on a school project and it's dictionary application using red black tree.. so the program reads a text file and every line has only one word.
when i do my search it gives me that the word is not available if i entered it with different letters size.. for example if the file has the word "Lion" and i searched "lion" in my program it says that the word is not available in dictionary.. here is my search method. And help me please to fix that.
public static int search(Node root,String data)
{
while(!root.isNullLeaf)
{ String temporary=root.data;
if(temporary.equals(data))
{
System.out.print("yaaay "+ root.data +" is found\n");
return 0;
}
if(temporary.compareTo(data)>0)
root=root.left;
if(temporary.compareTo(data)<0)
root=root.right;
}
System.out.println("ouch "+ data+ " not found\n");
return 1;
}
You should use the XXXIgnoreCase functions fore these type of requirements
temporary.equals(data) becomes temporary.equalsIgnoreCase(data) and temporary.compareTo(data) becomes temporary.compareToIgnoreCase(data)
I also corrected parts of the code to simplify your logic
public static int search(Node root,String data) {
while(!root.isNullLeaf) {
String temporary=root.data;
if(temporary.equalsIgnoreCase(data)) {
System.out.print("yaaay "+ root.data +" is found\n");
return 0;
}
int compareResult = temporary.compareToIgnoreCase(data);
if(compareResult > 0)
root = root.left;
else
root = root.right;
}
System.out.println("ouch "+ data+ " not found\n");
return 1;
}

why cant my function keep a total amount of int values within file?

I am making a program that reads a file of mixed values (int and string), prints only the integer values and keeps a running total of the amount of integer values within the file. Everything is working except for my running total of integer values within a given file and i am very confused on why it keeps printing 0 when i know there are more then 0 integer values within the file.
Here is my code:
package davi0030_a03;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class MyFile {
private String fileName; // name of the file
private int count = 0; // number of valid integers in the file
private final int MAX_SIZE = 10; // the size of the array
private Scanner inputStream = null;
private int[] theArray = new int[MAX_SIZE];
private boolean strangeInt = false;
private int total = 0;
// constructor to set the file name
public MyFile(String theName) { // constructor to set the file name
this.fileName = new String(theName);
// you may or may not want to do other stuffs here
}
public void openFile() {
System.out.println("opening file: " + fileName);
try {
inputStream = new Scanner(new FileInputStream("src/davi0030_a03/"
+ fileName));
} catch (FileNotFoundException e) {
System.out.println("File was not found or could not be opened");
}
}
// log a message on whether two ints in the file add to target
public void findPair(int target) {
openFile();
fileToArray();
findStrangeInt();
findTotal();
}
public void findTotal(){
inputStream.reset();
while(inputStream.hasNext()){
if(inputStream.hasNextInt()){
total +=1;
}
inputStream.next();
}
System.out.println(total);
}
public void findStrangeInt() {
inputStream.reset();
while (inputStream.hasNext()) {
try {
Integer.parseInt(inputStream.next());
} catch (NumberFormatException nfe) {
strangeInt = true;
}
}
if (strangeInt = true) {
System.out.println("File contains an incorrectly written int");
}
}
public void fileToArray() {
inputStream.reset();
while (inputStream.hasNext() && count < MAX_SIZE) {
if (inputStream.hasNextInt()) {
theArray[count] = inputStream.nextInt();
count++;
}
}
}
// print the content of the file
public void printFile() {
openFile();
inputStream.reset();
System.out.println("Printing content of file " + fileName);
while (inputStream.hasNext()) {
try {
int convert = Integer.parseInt(inputStream.next());
System.out.println(convert);
} catch (NumberFormatException nfe) {
System.out.println("xxx");
}
}
}
}
content of file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
a
b
d
EDIT: My solution below most likely solves the logic issue regarding your searching the file. However, I suggest you read some of the other comments the question has gotten. The IO handling here especially needs some improvement.
I believe your issue lies in your while statement. According to java documentation on the Scanner class,here, the method .hasNextInt() is returning based on the next element scanned. I think you are assuming it will return true as long as there are ints in the file. This is not the case. If the first thing the scanner hits is not an int, it is returning false and exiting your while loop. This would explain the returned 0, the value you initialize your variable 'total' to. I would suggest you do something like the following:
while(scanner.hasNext()){
if(scanner.hasNextInt()){
total +=1;
}
scanner.next();
}

Error on: Binary search tree on java with text file

Here's a program that will accept a text file (.txt, not Microsoft word or pdf stuff, just a basic text file) as a COMMAND LINE ARGUMENT and store each word (accepting ALL punctuation as if it were a space character, including apostrophe's) in a binary tree. Each node in the tree stores an ArrayList which holds the number of times that word occurs(first element) and each position in the text file that it occurs (all following elements). The user is shown the total number of words, and you can search for a word to see how many times and where in the file it is stored.
The code is not mine the autor is MasudKhan, i'm learning with it how to do my own code for a similar program.
I have been having some trouble finding the error with this code and why it's not working, the error message is:
"Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at A3Driver.main(A3Driver.java:10)"
A3Driver.java
/**
Assignment3
This class is a driver for a program which reads in a file,
whose name is given as a command line argument, and stores each
word as well as how many occurences of that word and the positions of
each occurence in the text file. The program then offers to allow
the user to search for any input word and produce the info for it,
if any.
*/
import java.io.*;
import java.util.*;
public class A3Driver
{
/**
main method for Binary word search program.
*/
public static void main(String[] args)
{
WordBST newTestWordBST = new WordBST(new File(args[0]));
System.out.println("Total number of words in file: " +
WordBST.wordPosition);
System.out.println("Number of unique words in file: " +
WordBST.uniqueWordCount);
System.out.print("Most used word: " + WordBST.mostUsedWord);
System.out.println(", times used: " + WordBST.highestCount);
System.out.println("\n\n");
Scanner keyboard = new Scanner(System.in);
String input = "";
while(!input.equals("n"))
{
System.out.print("Search for word (y/n)? ");
input = keyboard.nextLine();
if(input.toLowerCase().equals("y"))
{
System.out.print("Enter word: ");
newTestWordBST.searchBinaryTree(keyboard.nextLine());
}
}
System.out.println("Thank you, goodbye.");
/**
To output all tree info, uncomment this section.
newTestWordBST.inOrderTraverse();
*/
}
}
WordBST.java
/**
Assignment3
This class holds a Binary search tree of WordBSTNodes.
*/
import java.io.*;
import java.util.*;
public class WordBST
{
WordBSTNode root;
static int wordPosition, uniqueWordCount = 0, highestCount;
static String mostUsedWord;
/**
Constructor: initializes the root to null.
*/
public WordBST()
{
root = null;
}
/**
Constructor: initializes root to parameter value.
#param theRoot the root of this WordBST object
*/
public WordBST(WordBSTNode theRoot)
{
root = theRoot;
}
/**
Constructor: initializes root to hold nodes containing the words and
data from the parameter file.
#param text the input file containing words
*/
public WordBST(File text)
{
try
{
BufferedReader bR = new BufferedReader(new FileReader(text));
root = readBinaryTree(bR);
}
catch(IOException e)
{
System.out.println("Error reading file. Exiting.");
System.exit(1);
}
}
/**
Wrapper method for the recursive add method.
#param item the item to add to the BST
*/
public void add(String item)
{
root = add(root, item);
}
/**
Postcondition: uses recursion to add item to the BST node in the
appropriate position, or add information to the matching node.
#param localRoot the local node being checked in the current call
#param item the item to add to the BST
*/
private WordBSTNode add(WordBSTNode localRoot, String item)
{
if(localRoot == null) // item not in tree - add it
{
uniqueWordCount++; // total distinct word count
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(1);
temp.add(wordPosition);
return new WordBSTNode(item, temp);
}
else if(item.compareTo(localRoot.word) == 0) // item == localRootData
{
localRoot.countAndPos.set(0, localRoot.countAndPos.get(0) + 1);
localRoot.countAndPos.add(wordPosition);
if(localRoot.countAndPos.get(0) > highestCount)
{
highestCount = localRoot.countAndPos.get(0);
mostUsedWord = localRoot.word;
}
return localRoot;
}
else if(item.compareTo(localRoot.word) < 0) //item < localRootData
{
localRoot.leftTree = add(localRoot.leftTree, item);
return localRoot;
}
else // item > localRootData
{
localRoot.rightTree = add(localRoot.rightTree, item);
return localRoot;
}
}
/**
Postcondition: performs an inorder traversal.
*/
public void inOrderTraverse()
{
inOrderTraverse(root);
}
/**
Perform an inorder traversal.
#param localRoot the current node being traversed
*/
private void inOrderTraverse(WordBSTNode localRoot)
{
if(localRoot.leftTree != null) // left
{
inOrderTraverse(localRoot.leftTree);
}
// middle
//output current root
System.out.print(localRoot.word);
for(int i = 0; i < localRoot.countAndPos.size(); i++)
{
System.out.print(", " + localRoot.countAndPos.get(i));
}
System.out.println();
if(localRoot.rightTree != null) // right
{
inOrderTraverse(localRoot.rightTree);
}
}
/**
Wrapper method for searchBinaryTree recursive method.
#param searchWord the String word to search for
*/
public void searchBinaryTree(String searchWord)
{
searchBinaryTree(searchWord, root);
}
/**
Postcondition: if word is found in the search, it is output along with
occurrence information, and if it is not found, not-found info is output.
#param searchWord the word to search for
#param localRoot the localRoot being checked in the current call
*/
public void searchBinaryTree(String searchWord, WordBSTNode localRoot)
{
if( (searchWord.compareTo(localRoot.word) < 0) &&
(localRoot.leftTree != null) )
{
searchBinaryTree(searchWord, localRoot.leftTree);
}
else if( (searchWord.compareTo(localRoot.word) > 0) &&
(localRoot.rightTree != null) )
{
searchBinaryTree(searchWord, localRoot.rightTree);
}
else if(searchWord.compareTo(localRoot.word) == 0)
{
System.out.println("Position number(s) of occurence(s):");
for(int i = 1; i < localRoot.countAndPos.size(); i++)
{
System.out.println("word #" + localRoot.countAndPos.get(i));
}
System.out.println("Word found.");
System.out.println("Occurences: " +
localRoot.countAndPos.get(0));
}
else
{
System.out.println("Word does not exist.");
}
}
/**
#param bR the bufferedReader to read from
#return returns a node containing the info from the file which the input
BufferedReader is reading from
*/
public WordBSTNode readBinaryTree(BufferedReader bR)
{
String data = "";
String temp;
try
{
while(bR.ready())
{
data = data.concat(bR.readLine().toLowerCase() + "\n");
}
if(data == "")
{
return null;
}
}
catch(IOException e)
{
System.out.println("Error reading file. Exiting.");
System.exit(1);
}
return readBinaryTree(
new StringTokenizer(data,
" \t\n\r\f.,!`'-\"\\:()[]{}=+_*&^%$##?<>;|/~"));
}
/**
#param inputST the StringTokenizer to repeatedly add words from
#return returns a node containing the info from the file which the input
BufferedReader is reading from
*/
public WordBSTNode readBinaryTree(StringTokenizer inputST)
{
wordPosition = 1;
ArrayList<Integer> tempArrayList =
new ArrayList<Integer>(wordPosition++);
tempArrayList.add(1);
WordBST tempBST = new WordBST(
new WordBSTNode(inputST.nextToken(), tempArrayList));
highestCount = 1;
mostUsedWord = tempBST.root.word;
while(inputST.hasMoreTokens())
{
tempBST.add(inputST.nextToken());
wordPosition++; // current position, and total words in file
}
return tempBST.root;
}
}
WordBSTNode.java
/**
Assignment3
This class holds a node for a binary search tree. The node includes
a pointer to it's left subtree and it's right subtree, as well as String
data, and an ArrayList containing the number of occurences of the
data in the user's input file in the first position, followed by the
word number in each following position.
*/
import java.util.*;
public class WordBSTNode
{
WordBSTNode leftTree;
WordBSTNode rightTree;
String word;
ArrayList<Integer> countAndPos;
/**
Constructor: no arg constructor must never be used to avoid
confusion between a null node element and a null element content.
*/
public WordBSTNode()
{
System.out.println("Cannot creat empty node, sorry.");
}
/**
Constructor: initializes parent, word, and countAndPos instance
variables.
#param theWord the word to be stored in this node
#param theCountAndPos an ArrayList containing this node's word's
count and position's
*/
public WordBSTNode(String theWord, ArrayList<Integer> theCountAndPos)
{
leftTree = null;
rightTree = null;
word = theWord;
countAndPos = theCountAndPos;
}
}
Any help is really apreciated.

`NullPointerException` thrown while searching text file [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
First, I keep getting a NullPointerException on the line I put in ** below.
Second, my program is giving the wrong output (I somehow got it to work but then it went back to error). It must be a logic error. I have a file directory.txt of 11 lines, each with a name on it. When I run my program to try to find a certain name, it only finds the first name on the first line and everything else, it can't find. How can I fix these 2 errors?
I have 2 classes. This is the first class Directory:
import java.util.*;
import java.io.*;
public class Directory {
//public static void main(String[] args) {
final int maxDirectorySize = 1024;
String directory[] = new String[maxDirectorySize];
int directorySize = 0;
File directoryFile = null;
Scanner directoryDataIn = null;
public Directory(String directoryFileName) {
directoryFile = new File(directoryFileName);
try {
directoryDataIn = new Scanner(directoryFile);
}
catch (FileNotFoundException e) {
System.out.println("File is not found, exiting!" + directoryFileName);
System.exit(0);
}
while (directoryDataIn.hasNext()) {
directory[directorySize++] = directoryDataIn.nextLine();
}
}
public boolean inDirectory(String name) {
boolean inDir = true;
for (int i = 0; i < directory.length; i++) {
**if (directory[i].equalsIgnoreCase(name))**
inDir = true;
else
inDir = false;
}
return inDir;
}
public boolean add(String name) {
if (directory.length == 1024)
return false;
for (int i = 0; i < directory.length; i++) {
if (directory[i].equalsIgnoreCase(name))
return false;
else
directory[directorySize++] = name;
return true;
}
return false;
}
public boolean delete(String name) {
for (int i = 0; i < directory.length; i++) {
if (directory[i].equalsIgnoreCase(name)) {
directory[i] = null;
return true;
}
else
return false;
}
return false;
}
public void closeDirectory() {
directoryDataIn.close();
PrintStream directoryDataOut = null;
try {
directoryDataOut = new PrintStream(directoryFile);
}
catch (FileNotFoundException e) {
System.out.printf("File %s not found, exiting!", directoryFile);
System.exit(0);
}
String originalDirectory[] = {"Mike","Jim","Barry","Cristian","Vincent","Chengjun","susan","ng","serena"};
if (originalDirectory == directory)
System.exit(0);
else
for (int i = 0; i < directorySize; i++)
directoryDataOut.println(directory[i]);
directoryDataOut.close();
}
}
AND this is my second class which I'm trying to run but I keep getting exception main thread NullPointerException.
import java.io.*;
import java.util.*;
public class DirectoryWithObjectDesign {
public static void main(String[] args) throws IOException {
String directoryDataFile = "Directory.txt";
Directory d = new Directory(directoryDataFile);
Scanner stdin = new Scanner(System.in);
System.out.println("Directory Server is Ready!");
System.out.println("Format: command name");
System.out.println("Enter ^Z to end");
while (stdin.hasNext()) {
String command = stdin.next();
String name = stdin.next();
if (command.equalsIgnoreCase("find")) {
if (d.inDirectory(name))
System.out.println(name + " is in the directory");
else
System.out.println(name + " is NOT in the directory");
}
else if (command.equalsIgnoreCase("add")) {
if (d.add(name))
System.out.println(name + " added");
else
System.out.println(name + " cannot add! " + "no more space or already in directory");
}
else if (command.equalsIgnoreCase("delete")) {
if (d.delete(name))
System.out.println(name + " deleted");
else
System.out.println(name + " NOT in directory");
}
else {
System.out.println("bad command, try again");
}
}
}
}
This code:
while (directoryDataIn.hasNext()) {
directory[directorySize++] = directoryDataIn.nextLine();
}
will only fill up as much of directory as there are lines in the input file (11 according to your question).
This code:
for (int i = 0; i < directory.length; i++) {
**if (directory[i].equalsIgnoreCase(name))**
will loop over every entry in directory, up to its length (1024).
Since 1013 of those entries are null, trying to run equalsIgnoreCase() on them will result in a NPE.
Edit
You can solve this one of several ways. For instance, you could
keep track of the number of lines you read, and only read up to that point
check each entry to see if it is null before evaluating it
use a dynamically sized data structure instead of an array, such as ArrayList
perform the check on the known value (e.g. if (name.equalsIgnoreCase(directory[i])))
etc.
Change
for (int i = 0; i < directory.length; i++) {
To
for (int i = 0; i < directorySize; i++ ){
directorySize is already Keeping track of the number of entries so any array entries above that will be null. Therefore trying to call equalsIgnoreCase() on them will get a NPE.
Actually this looks like a prime use for ArrayList rather than array. The list will expand as you need it and List.size() will give you the correct length.

Categories

Resources