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

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".

A form for saving objects in a CSV file in Java - Files and I/O in Java

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

 

Previous article
Working with text files in Java
All articles in this section
Files and I/O in Java
Skip article
(not recommended)
Storing objects in CSV format in Java, part 2
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