2

I'm attempting to make a login system by using a model and DAO class to write users to a file called users.txt

In my controller, I created an initialize method:

public void initialize(){
    User user = new User();
    user.addUser();
}

Here's the part of my model that contains the addUser() method:

public void addUser() {
    User newUser = new User();
    UserDAO uDAO = new UserDAO();
    uDAO.createUser(newUser);
}

And this is my DAO class(I can't just paste the createUser() method as it links to several other methods in the class):

package Server;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Scanner;

public class UserDAO implements UserDAOInterface {

    private static final String User_File = "users.txt";
    private File dataFile;

    public UserDAO() {
        Path dPath = FileSystems.getDefault().getPath("src/MainMenu",User_File);
        dataFile = new File(dPath.toString());
    }

    public ArrayList<User> getAllUsers() {
        Scanner sc;
        String record = null;
        String[] fields;
        ArrayList<User> users = new ArrayList<User>();

        try {
            sc = new Scanner(dataFile);
            while (sc.hasNextLine()) {
                record = sc.nextLine();
                fields = record.split(";");
                String username = fields[0];
                String password = fields[1];
                User u = new User();
                users.add(u);
            }
        } catch (FileNotFoundException e) {
            System.out.println("No record found!");
            //e.printStackTrace();
        }
        return users;
    }

    public User getUser(String username) {
        ArrayList<User> users = getAllUsers();
        User user = null;
        for (User u: users) {
            if (u.getUsername().equals(username)) {
                user = u;
                break;
            }
        }
        return user;
    }

    public boolean createUser(User user) {
        boolean existing = false;
        ArrayList<User> users = getAllUsers();
        for (User u: users) {
            if (u.getUsername().equals(user.getUsername())) {
                existing = true;
                break;
            } 
        }
        if (!existing) {
            users.add(user);
            synToFile(users);
        }
        return !existing;
    }

    public void updateUser(User user) {
        ArrayList<User> users = getAllUsers();
        for (int i = 0; i < users.size(); i++) {
            User u = users.get(i);
            if (u.getUsername().equals(user.getUsername())){
                 users.set(i, user);
            }
        }
        synToFile(users);
    }

    public void deleteUser(User user) {
        ArrayList<User> users = getAllUsers();
        User delUser = null;
        for (User u: users) {
            if (user.getUsername().equals(u.getUsername())){
                delUser = u;
                break;
            }
        }
        if (delUser != null) {
            users.remove(delUser);
            synToFile(users);
        } 
    }

    public void synToFile(ArrayList<User> userList) {
        if (userList == null) {
            return;
        }

        try {
            FileWriter out = new FileWriter(dataFile);
            for (User u: userList) {
                out.append(u.toString() + "\n");
        }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}

I've imported everything I needed to import, and all paths are correct. I've tried deleting the text file and running the application to see if the path works, and it does manage to create the text file, but it doesn't update the file by writing anything to it.

I suspect the issue might have something to do with not creating any password for the user, and since there isn't a password field it can't write anything; but I can't figure out a way around this.


Also, nothing else in the model is important; just some attributes, accessors and mutators, and a default constructor that doesn't contain anything.


Update: Added the User class here for reference.

package Server;


public class User {

    private String username;
    private String password;

    public User() {

    }

    public void addUser() {
        User newUser = new User();
        UserDAO uDAO = new UserDAO();
        uDAO.createUser(newUser);
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
cosmo
  • 751
  • 2
  • 14
  • 42

3 Answers3

4

When syncing the users to the file, you need to close your stream:

try {
  FileWriter out = new FileWriter(dataFile);
  for (User u: userList) {
     out.append(u.toString() + "\n");
  }
  out.close(); // <- new!

} catch (IOException e) {
   e.printStackTrace();
} 

Also make sure that your file exists, otherwise you'll throw a FileNotFoundException in your getAllUsers() method.

Jan B.
  • 6,030
  • 5
  • 32
  • 53
  • This allowed me to write things into the file, though I'm not exactly sure what was written. The text file now contains this: Server.User@712918d8. My intention was to write the username and password to it; I'm aware I haven't assigned a password yet, but it should still at least show `newUser`, right? – cosmo Jan 18 '17 at 04:03
  • @cosmo you need to implement toString() method in the User class – mc20 Jan 18 '17 at 04:04
  • @mc20 Where exactly should I be implementing this method? I've added the User class to the question for reference. – cosmo Jan 18 '17 at 04:12
  • This is leading to a more complex issue. toString(), which you need to override in your user class by the way, is definitely an option if you want to print the data in a quick and readable format to file. Problems will raise when you want to read the data from the file back to your application. You should read upon object serialization. https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html – Jan B. Jan 18 '17 at 04:15
0

System.out.println is always your friend when it comes to debugging. I'm not sure the code is complete enough for anyone to be able to give you a solid reply. Place printlns at the start of each method in question (or use a debugger and step through each area). Maybe something with the existing user check is going wrong?

Jon Sampson
  • 1,473
  • 1
  • 21
  • 31
  • I've already tried adding print statements to every single method involved with the initial `addUser()` method, and they've all printed successfully. – cosmo Jan 18 '17 at 03:55
0

Modified your User class and added toString method to it so you can use this method to print the user object

Like this

//Create New user
User user=new User();
user.setUsername("XYZ User");
user.setPassword("****");

//print the created user
System.out.println(user.toString());

And the output will be

User{username=XYZ User, password=***}

Added toString() method in User class

package Server;


public class User {

    private String username;
    private String password;

    public User() {

    }

    public void addUser() {
        User newUser = new User();
        UserDAO uDAO = new UserDAO();
        uDAO.createUser(newUser);
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    //toString() method which will return the String representation of User 
    @Override
    public String toString() {
        return "User{" + "username=" + username + ", password=" + password + '}';
    }
}

and if you want only the user name then remove the password and that double cotted text from return of toString() method

Hemant Sangle
  • 282
  • 3
  • 19