Scanner not working properly - java

Hello again fellow programmers. I have another problem that's puzzling me. I am trying to receive input from a user but always receive an "java.util.NoSuchElementException: No line found". I have tried all the methods I've searched with no luck. Here is my code:
import java.util.Scanner;
import java.io.*;
public class UserLog {
static String username;
static String password;
static String passcompare;
static File name;
static String Userfile = "username-";
static String Passfile = "password-";
public static void main(String[] args) {
menu();
}
public static void menu(){
boolean call = false;
try (Scanner in = new Scanner(System.in)) {
do {
System.out.println("Select an option: ");
System.out.println("1: New account \n"
+ "2: Existing account");
System.out.print("-");
int choice = in.nextInt();
in.nextLine();
switch(choice) {
case 1:
call = true;
System.out.println("\nNew account called\n");
userCreate();
break;
case 2:
call = true;
System.out.println("\nExisting account called\n");
login();
break;
default:
System.out.println("\nNot a valid option\n");
}
} while(!call);
in.close();
}
catch(Exception ex) {
System.out.println("Exception Text: " + ex);
}
}
static void login(){
try (Scanner in = new Scanner(System.in)) {
System.out.println("LOGIN SCREEN\n");
System.out.print("Username: ");
username = in.nextLine();
name = new File("user-" + username + ".txt");
if(name.exists()) {
System.out.println("Username exists");
System.out.print("Password: ");
password = in.nextLine();
//scans userfile for password
if(password.length() != 0 && password.length() >= 8 /* and password-username match */) {
System.out.println("Login successful");
in.close();
}
}
else {
System.out.println("Username doesn't exist in system");
System.out.println("Would you like to create this user? (y/n)");
System.out.print("-");
char choice = (char)System.in.read();
switch(choice) {
case 'Y':
case 'y':
System.out.println("Creating user " + username);
name = new File("user-" + username + ".txt");
name.createNewFile();
System.out.println("User created");
passCreate(name);
in.close();
break;
case 'N':
case 'n':
System.out.println("Denied creation of user");
in.close();
break;
default:
System.out.println();
}
}
in.close();
} catch (IOException ex) {
System.out.println("Exception Text: " + ex);
}
}
private static File nameCreate() {
try (Scanner user = new Scanner(System.in)) {
System.out.print("Enter Username: ");
username = user.nextLine();
name = new File("user-" + username + ".txt");
if(!name.exists()) {
name.createNewFile();
try (FileWriter fw = new FileWriter(name)) {
fw.write(Userfile + username + "\n");
fw.write(Passfile);
fw.flush();
fw.close();
}
catch(Exception ex) {
System.out.println("Exception Text: " + ex);
}
//puts lines of text in the file-
//username-"username"
//password-
//
System.out.println("User Created\n");
}
else if(name.exists()) {
System.out.println("User already exists\n");
nameCreate();
}
user.close();
}
catch(Exception ex) {
System.out.println("Exception Text: " + ex);
}
return name;
}
private static void passCreate(File user) {
username = user.toString();
System.out.println(username + "\n");
boolean code = false;
try (Scanner pass = new Scanner(System.in)) {
do{
//opens file and reads until line "password-" and appends it with created password once confirmed
System.out.println("Create a password");
System.out.print("Password: ");
password = pass.nextLine();
if(password.length() >= 8) {
System.out.print("Confirm Password: ");
passcompare = pass.nextLine();
if(password.equals(passcompare)) {
code = true;
System.out.println("Passwords match\n");
//stores password
}
else {
System.out.println("Passwords don't match\n");
}
}
else {
System.out.println("Password needs to be longer than 8 characters\n");
}
}while(!code);
pass.close();
}
catch(Exception ex) {
System.out.println("Exception Text: " + ex);
}
}
private static void userCreate() {
nameCreate();
passCreate(name);
}
}
It's ugly and incomplete, I know, but this problem has kept me from going further. I am able to get to the password creation if I go through existing user option and create a user that way, but if I try to go through the create new user, I get the no line exception. My question is: how do I create more lines for the scanner to use to be able to create a password, or what other options do I have for completing this task. I've tried hasNextLine() and that's what made me realize that there are no more lines. Thanks

Closing the Scanner instances causes the underlying InputStream to be closed and causes a NoSuchElementException to be thrown on subsequent reads. There's no need to close Scanner unless you wish subsequent reads to fail.
Create a single Scanner instance are use for all methods.
Don't close Scanner
Java is an OO language. Use non-static methods.
The result:
public class UserLog {
private String username;
// more variables...
private final Scanner in;
public UserLog() {
in = new Scanner(System.in);
}
public static void main(String[] args) {
UserLog userLog = new UserLog();
userLog.showMenu();
}
public void menu() {
boolean call = false;
do {
try {
System.out.println("Select an option: ");
System.out.println("1: New account \n" + "2: Existing account");
System.out.print("-");
int choice = in.nextInt();
in.nextLine();
switch (choice) {
case 1:
call = true;
System.out.println("\nNew account called\n");
userCreate();
break;
case 2:
call = true;
System.out.println("\nExisting account called\n");
login();
break;
default:
System.out.println("\nNot a valid option\n");
}
} catch (InputMismatchException e) {
System.out.println("Invalid option " + in.nextLine());
}
} while (!call);
}
...
}

Related

Entering an only alphanumeric string runs into a java.lang.IndexOutOfBoundsException but works like intended otherwise

I get an error when I try to type a password consisting only alphanumeric characters but loops the way I intended if I type symbols. This is my first time trying to make a program that writes and reads a file and I'm still stuck here. I tried to paste the entire code to a different class but still runs into the same situation. I have no clue what caused this error. The IDE I'm currently using is Eclipse.
The full error is:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
TaskPerf6.main(TaskPerf6.java:66)
Source:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
public class TaskPerf6 {
public static boolean isAlphaNumeric(String username) {
return username != null && username.matches("^[a-zA-Z0-9]*$");
}
public static boolean isAlphaNumeric1(String password) {
return password != null && password.matches("^[a-zA-Z0-9]*$");
}
public static void main(String[] args) throws IOException {
Scanner scan = new Scanner(System.in);
System.out.println("Type L to log-in or R to register.");
String choice = scan.nextLine();
File file = new File("records.txt");
FileWriter writer = new FileWriter(file);
//Register
if (choice.compareToIgnoreCase("R") == 0) {
System.out.println("Registration:");
while(true) {
try {
System.out.println("Write your username (Alphanumeric Characters Only):");
String username = scan.nextLine();
if (isAlphaNumeric(username)==true) break;
writer.write(username + "\n");
writer.close();
}
catch (java.lang.IndexOutOfBoundsException e) {
System.out.println("a");
}
catch (java.io.IOException e) {
System.out.println("");
}
}
while(true) {
try {
System.out.println("Write your password (Alphanumeric Characters Only):");
String password = scan.nextLine();
if (isAlphaNumeric1(password)==true) break;
writer.write(password + "\n");
writer.close();
}
catch (java.lang.IndexOutOfBoundsException e) {
System.out.println("a");
}
catch (java.io.IOException e) {
System.out.println("");
}
}
String line1 = Files.readAllLines(Paths.get("records.txt")).get(1);
}
}
}
You do not need two of the same methods; delete one of the isAlphaNumeric methods.
public static boolean isAlphaNumeric(String word) {
return word != null && word.matches("^[a-zA-Z0-9]*$");
}
Your problem is here:
String line1 = Files.readAllLines(Paths.get("records.txt")).get(1);
you are attempting to retrieve the second line of this file from the .get(1), when you have not wrote anything to the file.
The reason why you are not writing to a file is because you are using break whenever the username and password matches your regex pattern.
if (isAlphaNumeric(username)==true) break;
writer.write(username + "\n");
writer.close();
which will take you out of the while loop before you can write to the file.
You should practice breaking up your code for reusability. Very helpful: here is my solution for your task.
public class TaskPerf6 {
static String fileName = "records.txt";
static File file = new File(fileName);
static Scanner scan = new Scanner(System.in);
static final String REGISTER = "R";
static final String LOGIN = "L";
public static void main(String[] args){
System.out.println("Type L to log-in or R to register.");
String choice = scan.nextLine();
switch(choice.toUpperCase()) {
case REGISTER:
register();
break;
case LOGIN:
login();
break;
}
String line1 = getLineItem(0);
System.out.println(line1);
}
private static void login() {
// TODO
}
private static void register() {
while(true) {
System.out.println("Write your username (Alphanumeric Characters Only):");
String username = scan.nextLine();
if (processed(username))
break;
}
while(true) {
System.out.println("Write your password (Alphanumeric Characters Only):");
String password = scan.nextLine();
if (processed(password))
break;
}
}
private static boolean processed(String word) {
boolean success = true;
if (isAlphaNumeric(word)) {
if (!writeToFile(word)) {
System.out.println("Was unable to write to file");
success = false;
}
} else {
System.out.println("Was not alphanumeric, try again");
success = false;
}
return success;
}
private static boolean isAlphaNumeric(String word) {
return word != null && word.matches("^[a-zA-Z0-9]*$");
}
private static boolean writeToFile(String word ) {
boolean success = true;
try {
FileWriter writer = new FileWriter(file);
writer.write(word + "\n");
writer.close();
} catch (IndexOutOfBoundsException | IOException e) {
success = false;
}
return success;
}
private static String getLineItem(int i) {
String item = "";
try {
item = Files.readAllLines(Paths.get(fileName)).get(i);
} catch (IOException e) {
e.printStackTrace();
}
return item;
}
}
first change to be done might be not closing writer in the first loop for username but in second loop for password.
while(true) {
try {
System.out.println("Write your username (Alphanumeric Characters Only):");
String username = scan.nextLine();
if (isAlphaNumeric(username)==true){
System.out.println("username correct");
writer.write(username+"\n");
break;}
} catch (java.lang.IndexOutOfBoundsException e) {System.out.println("a");}
catch (java.io.IOException e) {System.out.println("");}
}
while(true) {
try {
System.out.println("Write your password (Alphanumeric Characters Only):");
String password = scan.nextLine();
if (isAlphaNumeric1(password)==true){
System.out.println("pass correct");
writer.write(password);
writer.close();
break;
}
}
catch (java.lang.IndexOutOfBoundsException e) {System.out.println("a");}
catch (java.io.IOException e) {System.out.println("");}
}
When record.txt cannot be found and you try to get index 1 that's why you're getting the index out of bound exception. Please use the following if check:
String line1;
if(!Files.readAllLines(Paths.get("records.txt")).isEmpty())
line1 = Files.readAllLines(Paths.get("records.txt")).get(1);

JAVA Match a Username with a Password for Login Program

I am coding a login program that allows you to set and store a password and username in two separate files (named accordingly). My problem is I can't figure out how to set a username to a password. Ex: Username is Bob, Password is cat, and the user needs to input Bob as the username and cat as the password or else it gives an error(if the user inputs the username as bill and the password as cat, it should detect that the username doesn't go with its respective password). Any help would be nice. *I have not added the username part yet as it is structured the same as the password part, I just need the username to correspond with the password so that the user cannot use a different username with the same password
Here is my code I have so far for a reference:
import java.io.File;
import java.io.PrintStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.FileReader;
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;
public class PassCode
{
static String adminPassword = "Change Password";
public static void fileMaker() throws IOException
{
PrintStream standard = System.out;
File f = new File("Password.txt");
FileOutputStream fs= new FileOutputStream(f);
PrintStream ps = new PrintStream(fs);
System.setOut(ps);
String theMessage = "Set New Password";
String userInput = JOptionPane.showInputDialog(theMessage);
System.out.println(userInput);
ps.close();
System.setOut(standard);
}
public static void Checker() throws IOException
{
Scanner inputStream = new Scanner(new FileReader("Password.txt")); //Scans declared file for text on the first line
String fileChecker = inputStream.nextLine(); //Sets scanned line into a string variable
if(fileChecker.isEmpty())
{
fileMaker();
}
else
{
int reply = JOptionPane.showConfirmDialog(null, "Would you like to change the current password", "Warning!", JOptionPane.YES_NO_OPTION);
if (reply == JOptionPane.YES_OPTION)
{
String inquire = "Type Administrator Password to Proceed";
boolean flag = true;
while(flag == true)
{
String confirm = JOptionPane.showInputDialog(inquire);
if(confirm.equals(adminPassword))
{
fileMaker();
flag = false;
}
else
{
inquire = "Incorrect!" + "\n" + "Retry";
}
}
}
}
}
public static void main(String[] args) throws IOException
{
Checker();
Scanner inputStreamThree = new Scanner(new FileReader("Password.txt"));
String line = inputStreamThree.nextLine();
String question = "Password Please";
Boolean right = true;
while(right == true)
{
String ask = JOptionPane.showInputDialog(question); //Asks for user to input password
if(ask.equals(adminPassword)) //Checks if user input the admin password
{
fileMaker();
Scanner inputStreamAdmin = new Scanner(new FileReader("Password.txt")); //Scans for admin password
String adminChecker = inputStreamAdmin.nextLine(); //Sets scanned line as a new string variable
line = adminChecker;
}
else if(line.equals(ask)) //Checks if user password is correct
{
System.out.println("Welcome Fellow Programmer to the Now Functioning Password Checker!" +
"\n" + "Date Today: 10/31/2017" +
"\n\n\n\n\n\n\n" + "Did you figure out the Admin password yet?");
right = false;
}
else if(ask != line) //Checks if user password is incorrect
{
question = "Incorrect Password!";
}
}
}
}
If both username and password are located in the same line number in their respective file, then it should be possible to deduct the right password for a given user.
Example:
Username.txt Password.txt
bob cat
alice rabbit
victor salmon
When searching the username, count the line read until you find the username. Then in the password file, read the number of lines and retrieve the password value. Then compare!
I assume this is academic work because storing password in clear in files is a major security hole and should never be allowed on professional project.
I assume that you use only single login but stored on 2 files Password.txt and Username.txt.
Below is my 10 min codes, so you might need to modified if got typo or error.
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class PassCodeA {
public static void main(String[] args)
{
Scanner usernameFile = null;
try {
usernameFile = new Scanner(new FileReader("Username.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Username File Missing", "File Missing", JOptionPane.CLOSED_OPTION);
return;
}
Scanner passwordFile = null;
try {
passwordFile = new Scanner(new FileReader("Password.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Password File Missing", "File Missing", JOptionPane.CLOSED_OPTION);
return;
}
String usernameInput = JOptionPane.showInputDialog(null,"Please Enter Username", "Username", JOptionPane.OK_CANCEL_OPTION);
String passwordInput = JOptionPane.showInputDialog(null,"Please Enter Password", "Username", JOptionPane.OK_CANCEL_OPTION);
System.out.println(usernameInput);
boolean usernameFound = false;
while(usernameFile.hasNextLine()){
final String lineFromFile = usernameFile.nextLine();
if(lineFromFile.equals(usernameInput)){
usernameFound = true;
break;
}
}
if (usernameFound == false) {
JOptionPane.showMessageDialog(null, "Username not found", "Username Not Found", JOptionPane.CLOSED_OPTION);
return;
}
boolean passwordFound = false;
while(passwordFile.hasNextLine()){
final String lineFromFile = passwordFile.nextLine();
if(lineFromFile.equals(passwordInput)){
passwordFound = true;
break;
}
}
if (passwordFound == false) {
JOptionPane.showMessageDialog(null, "Password not found", "Password Not Found", JOptionPane.CLOSED_OPTION);
return;
}
JOptionPane.showMessageDialog(null, "Thank you for login", "Success", JOptionPane.CLOSED_OPTION);
}
}
If you had multiple login credential in that both files. You should use LineNumberReader instead of scanner. So that you can match with line number on both files.
I found a way to implement LineNumberReader(LNR) and have the program check if the line numbers for both the username and password are the same. I used a separate method and called it in the main method. I tested the code and it worked with multiple username info and password info in both files. I know this is messy as well, but I was going for functionality first. Then I will optimize it accordingly. I cannot upload the whole code as it is way to big for space given.
Here is the code I added(just the method with the LNR):
public static void reader() throws IOException
{
JTextField username = new JTextField();
JTextField password = new JPasswordField();
Object[] message = {
"Username:", username,
"Password:", password
};
int option = JOptionPane.showConfirmDialog(null, message, "Login", JOptionPane.OK_CANCEL_OPTION);
boolean right = true;
while(right == true)
{
int u = 0;
String userCheck;
FileReader ur = null;
LineNumberReader lnru = null;
try {
ur = new FileReader("username.txt");
lnru = new LineNumberReader(ur);
while ((userCheck = lnru.readLine()) != null)
{
if (userCheck.equals(username.getText()))
{
break;
}
else
{
u = lnru.getLineNumber();
}
}
} catch(Exception e)
{
e.printStackTrace();
} finally {
if(ur!=null)
ur.close();
if(lnru!=null)
lnru.close();
}
int p = 0;
String passCheck;
FileReader pr = null;
LineNumberReader lnrp = null;
try {
pr = new FileReader("Password.txt");
lnrp = new LineNumberReader(pr);
while ((passCheck = lnrp.readLine()) != null)
{
if (passCheck.equals(password.getText()))
{
break;
}
else
{
p = lnrp.getLineNumber();
}
}
} catch(Exception e)
{
e.printStackTrace();
} finally {
if(pr!=null)
pr.close();
if(lnrp!=null)
lnrp.close();
}
if (option == JOptionPane.OK_OPTION)
{
if(password.getText().equals(adminPassword)) //Checks if user input the admin password
{
passMaker();
Scanner inputStreamAdmin = new Scanner(new FileReader("Password.txt")); //Scans for admin password
String adminChecker = inputStreamAdmin.nextLine(); //Sets scanned line as a new string variable
//lineFromFile = adminChecker;
}
else if(p == u) //Checks if username and password are correct
{
System.out.println("Welcome Fellow Programmer to the Now Functioning login program!" + "\n" + "Date Today: 10/31/2017" + "\n\n\n\n\n\n\n" + "Did you figure out the Admin password yet?");
right = false;
}
else //Checks if user password is incorrect
{
option = JOptionPane.showConfirmDialog(null, message, "Login Failed Try Again", JOptionPane.OK_CANCEL_OPTION);
}
}
}
}

NullPointerException on a static attribute

I am creating a simple login program in java. Here is the code i have so far.
import java.util.Scanner;
import java.io.*;
import java.util.Arrays;
public class PasswordProgram {
public static String user;
public String password;
public static boolean part1Finish = false;
public File file = new File("D:/file.txt");
public FileWriter UsernameWrite;
public char[] user1;
public void part1() {
System.out.println("Please create an account: ");
Scanner input = new Scanner(System. in );
System.out.println("Type in a username: ");
String user = input.next();
System.out.println("Type in a Password: ");
String password = input.next();
try {
UsernameWrite = new FileWriter(file);
UsernameWrite.write(user);
UsernameWrite.write(password);
System.out.println(user);
UsernameWrite.close();
part1Finish = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void part2() {
Scanner scan = new Scanner(System. in );
System.out.println("Please confirm your username: ");
String usercheck = scan.next();
int PassAttempts = 5;
int UserAttempts = 5;
user1 = user.toCharArray();
user1 = password.toCharArray();
char[] usernamecheck = java.util.Arrays.copyOfRange(user1, 0, user.length());
System.out.println(usernamecheck);
do {
if (usercheck.equals(usernamecheck)) {
while (PassAttempts > 0) {
System.out.println("Please confirm your password: ");
String passcheck = scan.next();
if (passcheck.equals(password)) {
System.out.println("Thank You ");
} else if (passcheck != password && PassAttempts > 0) {
PassAttempts--;
System.out.println("That is incorrect. Please Try Again");
passcheck = scan.nextLine();
} else {
System.out.println("You have run out of Password Attempts");
break;
}
}
} else if (usercheck != user && UserAttempts > 0) {
UserAttempts--;
System.out.println("That is an incorrect username. Please Try Again");
usercheck = scan.nextLine();
} else {
System.out.println("You have run out of Username Attempts");
break;
}
} while (UserAttempts > 0);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
PasswordProgram login = new PasswordProgram();
login.part1();
if (part1Finish == true) {
login.part2();
}
}
}
The problem i am getting is in the method part2. Here when I try to add the username that was saved under the variable user into a character array to use it as a range I get the error NullPointerException.
After investigating i see that when running part2 the value of user is null and therefore I get the error.
Is there a way I could do this through the FileReader method instead or how can i fix the current error I am getting ? Thank you.
Because the static field user is never assigned in part1, you get a NullPointerException when you try to use it in part2.
There are also other issues in the posted code:
why there is a file involved is unclear
you use != with String, for example in passcheck != password
you use equals between String and char[] in usercheck.equals(usernamecheck)
passcheck is assagned but never used
local variables (because of their names) are hiding some fields
UsernameWrite and UserAttempts have non conventional names (should be usernameWrite and userAttempts
You have two user variables declared, one which is static and has global scope, another which is local to part1(). When part2() is attempting to access user, it is using the static declaration, which is null. Your modifications to user in part1() are done to the local variable.
This is something called variable shadowing and should be avoided at all costs.
See the below example:
class Ideone
{
static String bla = "test1";
public static void myMethod() {
String bla = "test2";
System.out.println(bla);
}
public static void main (String[] args) throws java.lang.Exception
{
myMethod();
System.out.println(bla);
}
}
It outputs:
test2
test1

possible already open file error; halted

So, when I run this, I get no exceptions, but the execution halts. I entered a few lines of code to see where the hault is coming from. On initial execution, it creates a file in the path given in the Customer class. Once I do one of the actions, it doesn't let me go past the first debugging line. Ideas?
Heres the application:
package javaapplication18.pkg3;
import java.util.ArrayList;
import java.util.Scanner;
public class JavaApplication183 {
/**
* #param args the command line arguments
*/
static boolean keepGoing = true;
public static void main(String[] args) {
System.out.println("Welcome to the Customer Maintenance application");
//keepGoing = true;
Scanner sc = new Scanner(System.in);
while (keepGoing){
displayMenu();
String userChoice = getRequiredString("Enter a command: ", sc);
System.out.println("DEBUG LINE 1");
CustomerTextFile textFile = new CustomerTextFile();
System.out.println("DEBUG LINE 2");
performAction(userChoice, textFile);
System.out.println("DEBUG LINE 3");
}
// TODO code application logic here
}
public static void displayMenu() {
System.out.println();
System.out.println("COMMAND MENU");
System.out.println("list - List all customers");
System.out.println("add - Add a customer");
System.out.println("del - Delete a customer");
System.out.println("help - Show this menu");
System.out.println("exit - Exit this application");
System.out.println();
}
public static void performAction(String choice, CustomerTextFile textFile){
Scanner sc = new Scanner(System.in);
switch (choice.toLowerCase()) {
case "list":
//action
ArrayList<Customer> currentList = textFile.getCustomers();
for (Customer c : currentList) {
System.out.print(c.getEmail() + "\t");
System.out.print(c.getFirstName() + "\t");
System.out.println(c.getLastName());
}
break;
case "add":
String email = getRequiredString("Enter customer email address:", sc);
String firstName = getRequiredString("Enter first name:", sc);
String lastName = getRequiredString("Enter last name:", sc);
Customer c = new Customer(email, firstName, lastName);
textFile.addCustomer(c);
System.out.println(firstName + lastName + " was added to the database.");
break;
case "del":
String deleteUserByEmail = getRequiredString("Enter customer email to delete:", sc);
Customer delCustomer = textFile.getCustomer(deleteUserByEmail);
textFile.deleteCustomer(delCustomer);
break;
case "help":
//displayMenu();
break;
case "exit":
keepGoing = false;//exit();
break;
default:
System.out.println("You entereed something not in the list. Please try again.");
System.out.println();
}
}
public static boolean exit(){
System.out.println("Exit");
return false;
}
public static String getRequiredString(String prompt, Scanner sc) {
String s = "";
boolean isValid = false;
while (isValid == false) {
System.out.print(prompt);
s = sc.nextLine();
if (s.equals(""))
System.out.println("Error! This entry is required. Try again.");
else
isValid = true;
}
return s;
}
}
Here is the CustomerTextFile class:
package javaapplication18.pkg3;
import java.io.*;
import java.nio.file.*;
import java.util.ArrayList;
public class CustomerTextFile implements CustomerDAO{
private ArrayList<Customer> customers = null;
private Path customersPath = null;
private File customersFile = null;
public CustomerTextFile(){
customersPath = Paths.get("customers.txt");
customersFile = customersPath.toFile();
customers = this.getCustomers();
}
#Override
public Customer getCustomer(String emailAddress) {
for (Customer c : customers) {
if (c.getEmail().equals(emailAddress))
return c;
}
return null;
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public ArrayList<Customer> getCustomers() {
if (customers != null)
return customers;
customers = new ArrayList<>();
if (!Files.exists(customersPath)) {
try {
Files.createFile(customersPath);
}
catch (IOException e) {
return null;
}
}
if (Files.exists(customersPath)) {
try (BufferedReader in = new BufferedReader(new FileReader(customersFile))){
String line = in.readLine();
while(line != null) {
String[] columns = line.split("\t");
String email = columns[0];
String firstName = columns[1];
String lastName = columns[2];
Customer c = new Customer(email, firstName, lastName);
customers.add(c);
}
}
catch (IOException e) {
System.out.println(e);
return null;
}
}
return customers;
}
#Override
public boolean addCustomer(Customer c) {
customers.add(c);
return this.saveCustomers();
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public boolean updateCustomer(Customer c) {
Customer oldCustomer = this.getCustomer(c.getEmail());
int i = customers.indexOf(oldCustomer);
customers.remove(i);
customers.add(i, c);
return this.saveCustomers();
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public boolean deleteCustomer(Customer c) {
customers.remove(c);
return this.saveCustomers();
}
private boolean saveCustomers() {
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(customersFile)))){
for (Customer customer : customers) {
out.print(customer.getEmail() + "\t");
out.print(customer.getFirstName() + "\t");
out.println(customer.getLastName());
}
out.close();
return true;
}
catch (IOException e) {
return false;
}
}
}
Im not certain if the problem is in the application or if it is in the textfile class
run:
Welcome to the Customer Maintenance application
COMMAND MENU
list - List all customers
add - Add a customer
del - Delete a customer
help - Show this menu
exit - Exit this application
list
DEBUG LINE 1
Above was an example of the console output.
Why are you declaring a string inside the loop?
try this instead:
Scanner sc = new Scanner(System.in);
String userChoice;
do {
displayMenu();
userChoice = sc.nextLine(); //takes in the entire lien you type in
System.out.println("DEBUG LINE 1");
CustomerTextFile textFile = new CustomerTextFile();
System.out.println("DEBUG LINE 2");
performAction(userChoice, textFile);
System.out.println("DEBUG LINE 3");
} while(keepGoing);
Hope this helps

DeSerialized Object containing ArrayList has all null values

Hopefully someone can provide some insight on this issue. I have created an instance of an object that contains an ArrayList of information (username, password, password hint). I am trying to serialize the object. It looks like it is serializing properly, but when I restart the project to deserialize, it returns null values in the ArrayList. Why is it returning null values for the ArrayList objects?
Driver Class:
import java.io.Serializable;
public class TestingDriver implements Serializable{
private static final long serialVersionUID = 12345L;
private static TestingAccount users = new TestingAccount();
public static void main(String[] args) {
int foreverLoop = 0;
users = DeSerialize.main();
while (foreverLoop < 1) {
int selection = users.displayMainMenu();
if (selection == 1) {
users.listUsers();
}
else if (selection == 2) {
users.addUser();
}
else if (selection == 3) {
users.deleteUser();
}
else if (selection == 4) {
users.getPasswordHint();
}
else if (selection == 5) {
Serialize.main(users);
System.exit(0);
}
else {
System.out.println("That option does not exist. Please try again.");
}
}
}
}
TestingUser Class (objects of this class will populate the ArrayList):
import java.io.Serializable;
public class TestingUser extends UserAccount implements Serializable, Comparable <TestingUser> {
private static final long serialVersionUID = 12345L;
public TestingUser(String username, String password, String passwordHint) {
super(username, password, passwordHint);
}
public TestingUser() {
}
#Override
public void getPasswordHelp() {
System.out.println("");
System.out.println("Password hint: " + passwordHint);
System.out.println("");
}
#Override
public int compareTo(TestingUser otherAccount) {
if (this.username.compareToIgnoreCase(otherAccount.username) < 0) {
return -1;
}
else if (this.username.compareToIgnoreCase(otherAccount.username) > 0) {
return 1;
}
else {
return 0;
}
}
}
TestingAccount class (calling this class creates an object that contains the ArrayList):
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Scanner;
public class TestingAccount implements Serializable {
private static final long serialVersionUID = 12345L;
public ArrayList<TestingUser> userList;
private String username;
private String password;
private String passwordHint;
public TestingAccount() {
userList = new ArrayList<TestingUser>();
}
public void listUsers() {
for (int i=0; i<this.userList.size(); i++) {
System.out.println(this.userList.get(i));
}
}
#SuppressWarnings("resource")
public void addUser() {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a username: ");
username = input.next();
TestingUser tempAccount = new TestingUser(username, null, null);
if (this.userList.contains(tempAccount) == true) {
System.out.println("This user already exists.");
}
else {
System.out.println("Please enter a password: ");
password = input.next();
System.out.println("Please enter a password hint: ");
passwordHint = input.next();
tempAccount.password = password;
tempAccount.passwordHint = passwordHint;
this.userList.add(tempAccount);
System.out.println("Account " + tempAccount.username + " has been added.");
}
}
#SuppressWarnings("resource")
public void deleteUser() {
Scanner input = new Scanner(System.in);
System.out.println("Please enter the username to be deleted: ");
username = input.next();
TestingUser tempAccount = new TestingUser(username, null, null);
if (this.userList.contains(tempAccount) == true) {
int actIndex = this.userList.indexOf(tempAccount);
System.out.println("Please enter the password: ");
password = input.next();
tempAccount.password = password;
boolean passwordGood = this.userList.get(actIndex).CheckPassword(tempAccount);
int accountIndex = this.userList.indexOf(tempAccount);
tempAccount = this.userList.get(accountIndex);
if (passwordGood == true) {
this.userList.remove(actIndex);
System.out.println("The account has been deleted.");
}
else {
System.out.println("The password is not correct.");
}
}
else {
System.out.println("The account does not exist.");
}
}
#SuppressWarnings("resource")
public void getPasswordHint() {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a username: ");
username = input.next();
TestingUser tempAccount = new TestingUser(username, null, null);
if (this.userList.contains(tempAccount) == true) {
int actIndex = this.userList.indexOf(tempAccount);
tempAccount = this.userList.get(actIndex);
System.out.println("The password hint isL: " + tempAccount.passwordHint);
}
else {
System.out.println("The account does not exist.");
}
}
#SuppressWarnings({ "resource" })
public int displayMainMenu() {
int selection = 0;
Scanner input = new Scanner(System.in);
System.out.println("");
System.out.println("System Menu:");
System.out.println("1. List Users");
System.out.println("2. Add User");
System.out.println("3. Delete User");
System.out.println("4. Get Password Hint");
System.out.println("5. Quit");
System.out.println("");
System.out.println("What would you like to do?");
selection = input.nextInt();
return selection;
}
}
Serialize class:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Serialize {
public static void main(TestingAccount users) {
try {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("serialize"));
oos.writeObject(users);
oos.close();
} catch (FileNotFoundException e1) {
System.err.println("File not found.");
} catch (IOException e2) {
System.err.println("Unable to serialize.");
e2.printStackTrace();
}
}
}
Deserialize class:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeSerialize {
public static TestingAccount main() {
TestingAccount deSerialize = null;
try {
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("serialize"));
deSerialize = (TestingAccount) ois.readObject();
ois.close();
} catch (FileNotFoundException e1) {
System.err.println("Unable to open file.");
} catch (IOException e2) {
System.err.println("Could not de-serialize.");
e2.printStackTrace();
} catch (ClassNotFoundException e3) {
System.err.println("Could not cast to class TestingAccount.");
}
return deSerialize;
}
}
It looks like UserAccount isn'tSerializable. So when you serialize the derived TestingUser class, none of the UserAccount data gets serialized. See Object Serialization Specification #2.1.13(a). TestingUser doesn't have any instance state of its own to serialize.
The solution is to make UserAccount implement Serializable.
Not sure why this comes as a surprise.

Categories

Resources