0

I wrote a program to keep a user out unless they know the username and password. It's just a program I wrote for fun, and it doesn't really have a purpose. However, while testing the code I noticed an issue when trying to read from a file that was recently written to. For whatever reason the scanner object I created for the username.txt file, userOut, doesn't detect their is anything in the file (i.e. .hasNextLine() returns false), but only if it was written to within the program. If I write some text to the file, then run the program, it works just fine. Please note that the password.txt file works completely fine. Why is this happening?

Here's my code:

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;

public class Challenge5 {

public static void main(String[] args) {
    try {
        File usernameFile = new File("username.txt");
        File passwordFile = new File("password.txt");

        PrintWriter userOut = new PrintWriter(new FileOutputStream(usernameFile, true));
        PrintWriter passOut =  new PrintWriter(new FileOutputStream(passwordFile, true));

        Scanner in = new Scanner(System.in);

        Scanner userIn = new Scanner(usernameFile, "UTF-8");
        Scanner passIn = new Scanner(passwordFile, "UTF-8");

        System.out.println("Welcome to Luke's secure program.");
        if (!userIn.hasNextLine() || !userIn.hasNextLine()) {
            System.out.println("New users must set up their account: ");
            if (!userIn.hasNextLine()) {
                System.out.print("Enter a username: ");
                String username = in.nextLine().trim();
                userOut.print(username);
                userOut.flush();

            }
            if (!userIn.hasNextLine()) {
                System.out.print("Enter a password: ");
                String password = in.nextLine().trim();
                passOut.print(password);
                passOut.flush();

            }
            System.out.println("Your account has been created. You may now log in:");
        }

        System.out.print("Please enter username: ");
        String username = in.nextLine().trim();

        System.out.print("Please enter password: ");
        String password = in.nextLine().trim();

        String fileUsername = "";           
        while (userIn.hasNextLine()) {
            fileUsername = userIn.nextLine();
        }
        System.out.println(fileUsername);

        String filePassword = "";
        while (passIn.hasNextLine()) {
            filePassword = passIn.nextLine();
        }
        System.out.println(filePassword);

        if (username.equals(fileUsername) && password.equals(filePassword)) {
            System.out.println("Welcome!");


            while (true) {
                System.out.println("What would you like to do? ");
                System.out.println("1. Change username\n2. Change password\n3. Exit");
                System.out.print("> ");

                int choice;
                while (!in.hasNextInt()) {
                    System.out.println("What would you like to do? ");
                    System.out.println("1. Change username\n2. Change password\n3. Exit");
                    System.out.print("> ");
                    in.next();
                }
                choice = in.nextInt();
                in.nextLine();

                if (choice == 1) {
                    userOut = new PrintWriter(new FileOutputStream(usernameFile, false));
                    System.out.print("Enter new username: ");
                    String newUsername = in.nextLine().trim();
                    userOut.print(newUsername);
                    userOut.flush();
                } else if (choice == 2) {
                    passOut = new PrintWriter(new FileOutputStream(passwordFile, false));;
                    System.out.print("Enter new password: ");
                    String newPassword = in.nextLine().trim();
                    passOut.print(newPassword);
                    passOut.flush();
                } else if (choice == 3) {
                    System.out.println("Goodbye!");
                    break;
                } else {
                    System.out.println("Please try again.");
                }
            }
        } else {
            System.out.println("INVALID USERNAME OR PASSWORD, EXITING PROGRAM...");
        }

        userOut.close();
        passOut.close();
        in.close();
        userIn.close();
        passIn.close();

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
}

I recognize my code isn't perfect, but I think it should at the very least work. Any help would be appreciated.

  • you have userIn.hasNextLine() twice instead of passIn.hasNextLine() in your first if condition – Raf Dec 02 '15 at 23:57

1 Answers1

0

You need to reinitialize your Scanner objects to open input stream to the updated files content.

System.out.print("Please enter password: ");
String password = in.nextLine().trim();

Just after above two lines, you need the following:

userIn = new Scanner(usernameFile, "UTF-8");
passIn = new Scanner(passwordFile, "UTF-8");

The reason you fail to read nothing is because you open input stream connection to file username and password using userIn and passIn when there is nothing in file. Adding the above two lines open new input stream connection to the updated file hence, you will be able to read the content.

You seem to be having a bit of issue with your conditions below:

//if (!userIn.hasNextLine() || !userIn.hasNextLine()) {
  if (!userIn.hasNextLine() || !passIn.hasNextLine()) {
            System.out.println("New users must set up their account: ");
            if (!userIn.hasNextLine()) {
                System.out.print("Enter a username: ");
                String username = in.nextLine().trim();
                userOut.print(username);
                userOut.flush();

            }
            //why again !userIn.hasNextLine(), you should check passIn
            //if (!userIn.hasNextLine()) {
              if (!passIn.hasNextLine()) {
                System.out.print("Enter a password: ");
                String password = in.nextLine().trim();
                passOut.print(password);
                passOut.flush();

            }
            System.out.println("Your account has been created. You may now log in:");
        }

I have fixed the two conditions and commented out your code bit.

Raf
  • 7,505
  • 1
  • 42
  • 59
  • Yeah, I deleted most of the comment, but missed that part. Oops. As a side note, the person who commented pointed out an issue in my program, but fixing it by putting passIn instead of userIn made it so the password.txt file was reported as empty. Does the problem lie with the .hasNextLine() file? (I didn't think you had to reopen the input stream like that if you change the file at all.) – Luke Krauss Dec 03 '15 at 00:23
  • @LukeKrauss you have one if condition where you check if (!userIn.hasNextLine() || !passIn.hasNextLine()) and the purpose is to ask for user and pass if they are empty, inside that condition you have two another if conditions. Both of these conditions use userIn.hasNextLine() however, only first one should user userIn.hasNextLine() and the other condition that write to password.txt should user passIn.hasNextLine(). If you have updated just the first condition and left the other then, obviously when you write in username.txt in first condition, the second condition become false, so updated them – Raf Dec 03 '15 at 00:51
  • As far as re-opening the input stream to be able to read is concerned, it is tricky and you could read more in this question http://stackoverflow.com/questions/4149/how-do-i-use-java-to-read-from-a-file-that-is-actively-being-written – Raf Dec 03 '15 at 00:58
  • 1
    Alternatively, you can open the file just once, for both reading and writing, using the class RandomAccessFile. – Klitos Kyriacou Dec 03 '15 at 01:15
  • Exactly RandomAccessFile can be useful files that are being updated and read – Raf Dec 03 '15 at 01:18