Lesson 4 - Storing objects in the CSV format in Java
In the previous lesson, Working with text files in Java, we showed you how to write and read text files. The application we made was simple, like from a textbook. Let's create a real user database today using text files. Of course, we're going to store objects, so you can easily alter the program to store diary reminders, high scores for a game, animals in a shelter, or whatever you need to store.
The CSV format
We don't have to invent a complex method of storing data in text files because a proven and standard one already exists. This approach is called CSV (Comma Separated Values), where values are separated by commas or semicolons. We mentioned CSV in the article about the split() and join() string methods. In today's tutorial, we're going to need them.
Let's agree on what the User
class will look like. Once we
establish that, we'll demonstrate how its instances will be saved in CSV. Create
a new Java Swing project and create a new
JFrame
. Of course, you can use JavaFX as well if you like. Then,
add a User
class to it. We'll store their names, ages, and
registration dates. The constructor will initialize the instance based on these
three properties. We'll override the toString()
method so it'll
return the user's name. The class will look like this:
public class User { private String name; private int age; private LocalDate registered; public User(String name, int age, LocalDate registered) { this.name = name; this.age = age; this.registered = registered; } public String getName() { return name; } public int getAge() { return age; } public LocalDate getRegistered() { return registered; } @Override public String toString() { return name; } }
Don't forget to import LocalDate
.
Now, let's take a look at how users will appear in the CSV format. Each line will represent a single user. The user's properties will be separated by semicolons. For example, a user named John Smith, who is 22 years old and registered on March 21, 2000, would look like this:
John Smith;22;3/21/2000
We can see at first sight that the file is relatively easy to read. However, anyone who isn't aware of the application's design probably won't guess what the number 22 represents and what the date is for.
The file can obviously contain multiple users, i.e. more lines.
Since we're programming according to object-oriented practices, we'll create
a class for our database as well. It'll contain a collection of users,
represented by a DefaultListModel
class instance. We choose this
collection so we can bind it to the Swing ListView
and display our
users in the form easily. The collection will be private and adding users (or
deleting them, searching for, etc.) will be done using public methods. Finally,
the database will contain methods to load the CSV file and to store the database
contents to it. The filename will be another one of the database's private
fields. Add a new class, named Database
, to the project and prepare
its methods:
class Database { DefaultListModel<User> users; private String file; public Database(String file) { } public void addUser(String name, int age, LocalDate registered) { } public List<User> getAll() { } public ListModel<User> getModel() { } public void save() throws IOException { } public void load() throws IOException { } }
NetBeans will then underline the getAll()
method in red because
it doesn't return a value, but we'll ignore that for now. We'll do it all step
by step starting with the constructor.
In the constructor, we'll create an ArrayList
instance and store
the path to the database file:
public Database(String file) { users = new DefaultListModel<>(); this.file = file; }
That was very easy, so we'll move right on to next method:
public void addUser(String name, int age, LocalDate registered) { User u = new User(name, age, registered); users.addElement(u); }
The getModel()
method just returns the user collection:
public ListModel<User> getModel() { return users; }
The getAll()
method will return all of the users. Similarly, we
can create methods for searching for certain users. We'll return the users as an
array.
public List<User> getAll() { return Collections.list(users.elements()); }
Saving the users to CSV
Now, we'll finally get to work with the CSV file. Let's start by adding a
try
-catch
block with a BufferedWriter
instance. We'll iterate over our user list internally and create a
String[]
array for each user based on their properties. We'll have
to convert all of the non-string properties explicitly to strings. Then, we'll
join the array to make a long String
in which the items are
separated by semicolons. We'll use the join()
method to do just
that. Unlike split()
, we call the join()
method
directly on the String
class and we specify the "glue" (the text
used to join the items) as a String
too, not a char
.
Let's get right to it:
public void save() throws IOException { // opens the file for writing try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) { // iterates over the users for (User u : getAll()) { // creates an array of the user's values String[] values = {u.getName(), String.valueOf(u.getAge()), u.getRegistered().toString()}; // creates a new line String line = String.join(";", values); // writes the line bw.append(line); // writes "enter", so we more to the next line bw.append("\n"); } // flushes the buffer bw.flush(); } }
Let's try it all out, start by moving to the form file
(MainJFrame.java
). We'll create a private database
field to which, in the form's constructor, we'll create an instance of our
database:
private Database database; public MainJFrame() { initComponents(); database = new Database("users.csv"); }
Now, let's add a new button to the form, name it saveButton
, and
set its text to "Save"
.
In its Click handler, which is generated by double-clicking the button), we'll add 2 users to the database. It'll only be for testing purposes now, the application will look better later on. Next, we'll store the entire database into a file.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { try { database.addUser("John Smith", 22, LocalDate.of(2000, 3, 21)); database.addUser("John Brown", 31, LocalDate.of(2012, 10, 30)); database.save(); } catch (IOException ex) { JOptionPane.showMessageDialog(null, "Cannot save the database, verify your access privileges to the file."); } }
Run the application and click the button. Now open the users.csv
file in Notepad (in the project folder), which should have the following
content:
John Smith;22;3/21/2000 James Brown;31;10/30/2012
All of it works as it should We'll finish the application and be able to load users from the file in the next lesson - Storing objects in CSV format in Java, part 2.
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 3x (3.59 kB)
Application includes source codes in language Java