`NullPointerException` thrown while searching text file [closed] - java

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.

Related

Can't figure out why my counter is broken?

I am a somewhat intermediate-level Java programmer but I have had trouble with one of my recent programs. Basically the application is a Hangman game that allows the user to input letters in order to guess a word. Everything works okay except for the counter for how many lives the player has, in this case it is 5. The counter for some reason subtracts by 4 instead of 1, as well as this it takes away from the number of lives even if the letter is guessed correctly.
Any help would be widely appreciated, thank you in advance. The two classes are provided below. Also,
Instantiable Class
public class Hangman {
private char letterGuess;
private int numberLives;
private String outputWord;
private final String hiddenWord;
private final StringBuffer swapBuffer = new StringBuffer();
public Hangman() {
letterGuess = ' ';
numberLives = 5;
hiddenWord = "java";
outputWord = "";
for (int i = 0; i < hiddenWord.length(); i++) {
swapBuffer.append("*");
}
}
public void setLetterGuess(char letterGuess) {
this.letterGuess = letterGuess;
}
public void compute() {
for (int i = 0; i < hiddenWord.length(); i++) {
if (letterGuess == hiddenWord.charAt(i)) {
swapBuffer.setCharAt(i, letterGuess);
}
else {
numberLives--;
}
}
outputWord = swapBuffer.toString();
}
public int getNumberLives() {
return numberLives;
}
public String getHiddenWord() {
return hiddenWord;
}
public String getOutputWord() {
return outputWord;
}
}
Main Class
import javax.swing.*;
public class HangmanApp {
public static void main(String[] args) {
char letterGuess;
int numberLives;
String hiddenWord, outputWord, restartGame;
do {
Hangman myHangman = new Hangman();
JOptionPane.showMessageDialog(null, "Welcome to Java Hangman!");
JOptionPane.showMessageDialog(null, "In this game, a word will be printed to you in asterisks - each letter will be revealed upon a correct guess!");
JOptionPane.showMessageDialog(null, "You have 5 lives for the game, the game will end if you make too many incorrect guesses!");
for (int i = 0; i < 10; i++) {
hiddenWord = myHangman.getHiddenWord();
numberLives = myHangman.getNumberLives();
JOptionPane.showMessageDialog(null, "You currently have " +numberLives+ " lives!");
letterGuess = JOptionPane.showInputDialog(null, "Now, please enter a letter : ").charAt(0);
myHangman.setLetterGuess(letterGuess);
myHangman.compute();
outputWord = myHangman.getOutputWord();
JOptionPane.showMessageDialog(null, "The word so far is : " +outputWord);
}
numberLives = myHangman.getNumberLives();
JOptionPane.showMessageDialog(null, "You have finished the game with : " +numberLives+ " lives!");
restartGame = JOptionPane.showInputDialog(null, "Would you like to play again?");
}
while (restartGame.equalsIgnoreCase("Yes"));
}
}
Use a found boolean to check if the letter was found. If it wasn't, subtract a life.
var found = false;
for (int i = 0; i < hiddenWord.length(); i++) {
if (letterGuess == hiddenWord.charAt(i)) {
swapBuffer.setCharAt(i, letterGuess);
found = true;
}
}
if (!found) numberLives--;
If the guessed letter is wrong, in the compute function 1 life will be taken for each letter of the hidden word. You should try and use a switch(boolean) that will show you if the letter was found or not after parsing the whole word.
public void compute() {
// for (int i = 0; i < hiddenWord.length(); i++) {
// if (letterGuess == hiddenWord.charAt(i)) {
// swapBuffer.setCharAt(i, letterGuess);
// }
//
// else {
// numberLives--;
// }
// }
int letterNo = hiddenWord.length();
boolean found = false;
while (letterNo>0){
letterNo--;
if (letterGuess == hiddenWord.charAt(letterNo)){
swapBuffer.setCharAt(letterNo, letterGuess);
found = true;
}
}
if (!found){
numberLives--;
}
outputWord = swapBuffer.toString();
}

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.

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();
}

Cannot Run *.java downloaded file

I have downloaded a java file needed for a coursework at college. However I find it impossible to run it. Eclipse won't give me the chance to even run it (only ant build), and if I use netbeans I get this exception :
Exception in thread "main"
java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: Uncompilable source code - class Hangman is public, should be declared in a file named Hangman.java
at Hangman. < clinit > (hangman(Case Conflict).java: 20)
Java Result: 1
If someone is kind enough to read through the code, I really do not know what to do next. I figure there has to be something wrong with the main class. Thanks!
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
class Hangman {
Scanner userInput;
private Set < Character > wrongGuesses;
private String[] answers = {
"leverets", "hatchlings", "puppies",
"kittens", "pullets", "goslings"
};
private String answer;
private String guessed;
private int maxTurns;
private int currentTurns;
private boolean inProgress;
private char nextGuess;
private boolean gameWin;
public Hangman() {
userInput = new Scanner(System.in);
wrongGuesses = new HashSet < Character > ();
inProgress = false;
gameWin = false;
maxTurns = 14;
currentTurns = 0;
// set answer somehow
answer = answers[0];
// set guessed to the correct number of dashes
StringBuilder sb = new StringBuilder();
for (int i = 0; i < answer.length(); i++) {
sb.append('-');
}
guessed = sb.toString();
}
/* start a new game */
public void startGame() {
inProgress = true;
startGameLoop();
}
/* the game loop. this method is the heart of the game */
private void startGameLoop() {
printInstructions();
while (inProgress) {
printStatus();
acceptGuess();
checkStatus();
}
printWinOrLose();
}
private void printInstructions() {
System.out
.println("Guess the word one letter at a time until you win or run out of turns. Good luck!");
}
private void printWinOrLose() {
if (gameWin) {
System.out.println("You win! The answer was " + answer);
} else {
System.out.println("You lose.");
}
}
private void printStatus() {
System.out.println("Guesses left: " + (maxTurns - currentTurns));
System.out.println("Current status: " + guessed);
System.out.println("Wrong guesses: " + getWrongAnswers());
}
/* get the next character from the player */
private void acceptGuess() {
System.out.println("Next guess: ");
String temp = userInput.next();
nextGuess = temp.charAt(0);
}
/* check what state the game is in */
private void checkStatus() {
// if already guessed, say already guessed.
if (wrongGuesses.contains(nextGuess)) {
System.out.println("You already guessed that!");
return;
}
// if guess is not in answer, update number of turns played and add
// guess to wrong guesses
// otherwise update the guessed variable
if (answer.indexOf(nextGuess) < 0) {
++currentTurns;
wrongGuesses.add(nextGuess);
} else {
updateGuessStatus();
}
// check to see if the player has won or lost
if (answer.equals(guessed)) {
gameWin = true;
inProgress = false;
}
if (currentTurns == maxTurns) {
inProgress = false;
}
}
/* update the guessed variable when there is a correct guess made */
private void updateGuessStatus() {
// replace - with nextGuess where appropriate
int index = answer.indexOf(nextGuess);
int lastIndex = answer.lastIndexOf(nextGuess);
StringBuilder sb = new StringBuilder(guessed);
if (index != lastIndex) { // more than one instance of the guess in the
// answer
// swap out in a loop
while (index != -1) {
sb.setCharAt(index, nextGuess);
int i = answer.indexOf(nextGuess, (index + 1));
index = i;
}
} else { // letter only appears once
// swap out just that one
sb.setCharAt(index, nextGuess);
}
guessed = sb.toString();
}
/* build a text representation of all the incorrect guesses */
private String getWrongAnswers() {
if (wrongGuesses.size() > 0) {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (Character c: wrongGuesses) {
sb.append(c + ",");
}
sb.deleteCharAt(sb.length() - 1); // delete trailing comma
sb.append(')');
return sb.toString();
} else {
return "<none>";
}
}
public static void main(String[] args) {
Hangman h = new Hangman();
h.startGame();
}
}
The exception says everything you need to know. Rename the class FILE to Hangman.java.
Caused by: java.lang.RuntimeException: Uncompilable source code - class Hangman is public, should be declared in a file named Hangman.java
You should save your downloaded file in Hangman.java and not hangman.java (see it needs 'H' in caps same as your class name).
Change the class to public class Hangman. It allows outside methods to access it.
EDIT: I downloaded the file, changing the class to public worked. I also found an issue in the code itself, the word is always "Leverets".
To change this, edit the getAnswer() method and change it to
private int getAnswer() {
int i = (int) (Math.random() * 6) + 0;
return i;
}

Pattern Recognition

So my code is done, but now I need it to print out wether the chosen numbers are equal or not!
I've made a loop for FALSE / NUMBERS ARE EQUAL, but it doesn't work properly.
Hope you can help.
My code looks like this:
package patternrecognition;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
public class PatternRecognition {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int AntalNumre = -1;
boolean Gyldignummer = false;
while (Gyldignummer == false) {
System.out.print("\n\nIndtast antal numre: ");
String numre = reader.readLine().trim();
Gyldignummer = validInteger(numre);
if (Gyldignummer == false) {
System.out.println("Indtast et gyldigt nummer");
} else {
AntalNumre = Integer.parseInt(numre);
}
}
HashMap vaerdier = new HashMap();
for (int i = 0; i < AntalNumre; i++) { //Studerendes nummer(i+1)
boolean GyldigNummer2 = false;
while (GyldigNummer2 == false) {
System.out.print("\n\nIndtast en vaerdi for nummer " + (i + 1) + ": ");
String vaerdi = reader.readLine().trim();
int vaerdien = -1;
GyldigNummer2 = validInteger(vaerdi);
if (GyldigNummer2 == false) {
System.out.println("Indtast et gyldigt nummer");
} else {
vaerdien = Integer.parseInt(vaerdi);
}
vaerdier.put(vaerdi, new Integer(vaerdien));
}
}
TreeMap SorteretNummer = new TreeMap(vaerdier);
Iterator nr = SorteretNummer.keySet().iterator();
System.out.println("\n\n\n\n\n");
System.out.println("Numre valgt:");
System.out.println("------------");
while (nr.hasNext()) {
String navn = (String) nr.next();
int numre = ((Integer) SorteretNummer.get(navn)).intValue();
System.out.println("" + numre);
if (numre != numre) {
System.out.println("FALSE");
}
else {
System.out.println("ALLE THE NUMBERS ARE EQUAL");
}
}
}
public static boolean validInteger(String nummer) {
boolean validInteger = false;
try {
Integer.parseInt(nummer);
validInteger = true;
} catch (NumberFormatException nfe) {
validInteger = false;
}
return validInteger;
}
}
Well, numre != numre is bound to be false unless of course numre happens to be changed in another thread (or be NaN, but that's a different story).
Perhaps, you may want to compare pairs of numbers? Or, perhaps, you want to have a data structure holding the numbers you've already seen (e.g. HashSet or BitSet)?
An example: as user enters numbers, save those to a HashSet<Integer>. As soon as he's done, add
Set<Integer> set = new hashSet<Integer>();
// ...as we're getting numbers from user
set.add(numre);
// ...
if (set.size() == 1)
System.out.println("OMG they're all the same! " + set);
This is a problem:
if (numre != numre) {
System.out.println("FALSE");
}
else {
System.out.println("ALLE THE NUMBERS ARE EQUAL");
}
Comparing the same variable to itself: will always print "ALLE THE NUMBERS ARE EQUAL".
EDIT:
Remember the previously entered Integer and compare to the most recently entered Integer. Use Integer and initialise the previousInt to null so you know to avoid comparison on initial loop iteration.
As it is homework I will not post the code and it will be more benefit to you if you code it yourself.

Categories

Resources