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:
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:
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 13x (41.97 kB)
Application includes source codes in language Java