Get up to 80 % extra points for free! More info:

Lesson 5 - Storing objects in CSV format in Java, part 2

In the previous lesson, Storing objects in the CSV format in Java, we started coding an application for storing users in CSV files. In today's Java tutorial, we're going to finish and improve this application.

Loading users from the CSV file

Now that saving works, all that's left for us to do is to load the data back into the application. We'll read the file line by line, split each line using the split() method, and then add an object with those values to the collection. We'll empty the collection before loading, so as to get rid of the users loaded from before (in case we extend the application in the future).

public void load() throws IOException {
    users.clear();
    // Opens the file for reading
    try (BufferedReader br = new BufferedReader(new FileReader(file))) {
        String s;
        // Reads it line by line
        while ((s = br.readLine()) != null) {
            // splits the string line using semicolons
            String[] values = s.split(";");
            String name = values[0];
            int age = Integer.parseInt(values[1]);
            LocalDate registered = LocalDate.parse(values[2]);
            // adds a new user with those values
            addUser(name, age, registered);
        }
    }
}

The database class is now complete. Let's focus on the form part now.

The application presentation layer

First, we'll prepare new form controls (from the Palette). We'll add a load button named loadButton, then a JList named userList. In Properties we'll switch to the Code tab and set Type Parameters to <User>. Next, JTextField for the name of the new user named nameJTextField, JSpinner for their age named ageJSpinner and JFormattedTextField for the registration date named registeredJFormattedTextField. We'll add some labels to these components. We can group these elements using a panel. In the next panel there will be 3 labels for the user's detail, which we'll name nameJLabel, ageJLabel, and registeredJLabel. We'll add 3 more labels as their labels. Finally, we'll add a button to add the user named addButton. If it was too fast for you, don't worry, here's a picture of the final form:

CSV user database form in Java - Files and I/O in Java

In a real application, adding users would probably be done in an entirely separate dialog. However, a single form is just fine for our purposes.

Let's remove the test users creation part from the "Save" button handler. Next, we'll add saving in a try-catch block. We already know that the finally keyword (the TWR block in our database) doesn't actually catch exceptions, which is what we want. Therefore, we'll react to them in the presentation layer (in the form), where we're supposed to. Error notifications, i.e. communicating with the user, would be done incorrectly if placed in the Database class. We'll pull up a JOptionPane if we catch an exception. With all of that in mind, the button's handling method will look like this:

private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {
    try {
        database.save();
    } catch (IOException ex) {
        JOptionPane.showMessageDialog(null, "Unable to save the database, check the file's access privileges.");
    }
}

We'll click a handler for the "Load" button in a similar manner. In real applications, the loading would probably be performed automatically when the application starts. However, we'll leave that to the buttons for the better control. The "Load" button method now looks as follows:

private void loadButtonActionPerformed(java.awt.event.ActionEvent evt) {
    try {
        database.load();
    } catch (IOException ex) {
        JOptionPane.showMessageDialog(null, "Unable to load the database. The file might not exist.");
    }
}

Now let's handle clicking events for the userList, which will display the user details to the labels that we've prepared:

private void userListValueChanged(javax.swing.event.ListSelectionEvent evt) {
    User user = userList.getSelectedValue();
    if (user != null) {
        nameJLabel.setText(user.getName());
        ageJLabel.setText(String.valueOf(user.getAge()));
        registeredJLabel.setText(user.getRegistered().toString());
    }
}

We added a condition in case no user is selected (the list would be empty).

There's one last button without a handler method and that's the one used to add new users. We'll click it, the handler will be very simple. We'll just add the user to the database and it'll take care of everything else:

private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
    String name = nameJTextField.getText();
    int age = (int) ageJSpinner.getModel().getValue();
    LocalDate registered = LocalDate.parse(
            registeredJFormattedTextField.getText(),
            DateTimeFormatter.ofPattern("d'.'M'.'y"));
    database.addUser(name, age, registered);
}

Let's try to add a new user:

A form for adding a new users in Java to a CSV file - Files and I/O in Java

We could implement removing users in a very similar fashion, but I'll leave this up to you.

Now we have to bind the database to the user list so it'll get updated every time the database changes. To do so we'll add the following line to the MainJFrame constructor.

userList.setModel(database.getModel());

Our application is almost done. Let's think for a bit about what would happen if someone wrote a semicolon in their name. As you may have guessed, the application would break. That's why we'll remove semicolons from the name in the save() method. If we needed to store semicolons in our application (which isn't a very common thing), we could come up with another separator. If we wanted things to be perfect, we'd add the value with the semicolon in quotes. However, the split() method will no longer suffice for parsing. Of course, we could also solve this problem by using a different file format. In this case, we'll simply remove semicolons. More accurately, we'll replace them with spaces by changing a single line in the save() method:

String[] values = {u.getName().replace(";", " "), String.valueOf(u.getAge()), u.getRegistered().toString()};

We're now done. If you had any problems, the finished project is attached below, as always. In the next lesson, Solved tasks for Java Files Lessons 1-5, we'll introduce the XML format.

In the following exercise, Solved tasks for Java Files Lessons 1-5, we're gonna practice our knowledge from previous lessons.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 12x (41.97 kB)
Application includes source codes in language Java

 

Previous article
Storing objects in the CSV format in Java
All articles in this section
Files and I/O in Java
Skip article
(not recommended)
Solved tasks for Java Files Lessons 1-5
Article has been written for you by Petr Štechmüller
Avatar
User rating:
No one has rated this quite yet, be the first one!
Activities