Introduction

This tutorial will show you how to handle the file usage in Java

The main goal of the exercise is to be able to read lists of objects from a file, previously filled it programmatically. The tutorial also shows how to manage a unique id in a file format

Exercise description

For the IAM software purpose, you need to persist Identities information, allowing you to save the user input

  • To provide a reusable logic, you will define a DAO interface and realize one implementation of that interface handling files accesses

  • You will need to constitute a file where you'll put all the identity information

  • You will need to access those information, being able to read all Identities information at once

Defining a DAO

What is a DAO? The DAO (for Data Access Object is a class responsible of the data management for one datamodel class

So every time you'll need to retrieve or to save a data model class, you should pass this data model as a parameter of one of the DAO methods, and the DAO will handle the rest for you. This has a major convenient side-effect: it makes your code testable

One logic, several realizations : using interfaces

Why should we use interface here? If you remember, an interface is the representation of a defined behaviour.

It allows to write the code logic (eg: the Identity is filled, it is passed to the DAO for persistence), once and if you want to change how the DAO is internally working, while letting your main logic untouched.

Define the DAO operations

As mentionned in the exercise description, the DAO should be able to write an identity and to read all identities. As a result, the DAO interface definition will look like:

and the result in Java
package fr.tbr.iamcore.dao;

import java.util.List;
import fr.tbr.iamcore.identity.Identity;

/**
 * Handles the storage of Identity objects
 * @author Tom
 */
public interface IdentityDAO {

	/**
	 * Allows to store the given identity
	 * @param identity
	 * @return true if the storage has been successful
	 */
	public boolean store(Identity identity);

	/**
	 * Retrieve all the stored identities
	 * @return a List of identities
	 */
	public List<Identity> getAllIdentities();

}

As you can see, this interface can do nothing by itself, except giving the main behaviour of the DAOs

Define the file implementation for IdentityDAO

We will define a new implementation by declaring this class

package fr.tbr.iamcore.dao;

import fr.tbr.iamcore.identity.Identity;

public class IdentityFileDAO implements IdentityDAO{

	@Override
	public boolean store(Identity identity) {
        return false;
	}

	@Override
	public List<Identity> getAllIdentities() {
         return null;

	}
}

First operation : store Identity objects

To achieve the Identity persistence in the file called idList.txt:

package fr.tbr.iamcore.dao;

import fr.tbr.iamcore.identity.Identity;

public class IdentityFileDAO implements IdentityDAO{


	@Override
	public boolean store(Identity identity) {
		File file = new File("/identities/idlist.txt");
		try {
			if (!file.exists()){
				file.createNewFile();
			}
			// append mode
			FileWriter fileWriter = new FileWriter(file, true);
			PrintWriter writer = new PrintWriter(fileWriter, true);
			writer.println("---Begin Identity---");
			writer.println(identity.getDisplayName());
			writer.println(identity.getEmail());
			writer.println("---End Identity---");
			writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;

	}

	@Override
	public List<Identity> getAllIdentities() {
        return null;
	}

}


Second operation : read all Identity objects

To achieve that, you will need to open the file again, and read its content

package fr.tbr.iamcore.dao;

import fr.tbr.iamcore.identity.Identity;

public class IdentityFileDAO implements IdentityDAO{


	@Override
	public boolean store(Identity identity) {
		File file = new File("/identities/idlist.txt");
		try {
			if (!file.exists()){
				file.createNewFile();
			}
			// append mode
			FileWriter fileWriter = new FileWriter(file, true);
			PrintWriter writer = new PrintWriter(fileWriter, true);
			writer.println("---Begin Identity---");
			writer.println(identity.getDisplayName());
			writer.println(identity.getEmail());
			writer.println("---End Identity---");
			writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;

	}

	@Override
	public List<Identity> getAllIdentities() {
        List<Identity> list = new ArrayList<Identity>();
		try {
			Scanner scanner = new Scanner(new FileReader("/identities/idlist.txt"));
			while(scanner.hasNext()){
				Identity currentIdentity = new Identity();
				String string = scanner.nextLine();
				currentIdentity.setDisplayName(scanner.nextLine());
				currentIdentity.setEmail(scanner.nextLine());
				list.add(currentIdentity);
				scanner.nextLine();
			}
			scanner.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;

	}

}

Example of usage

//...
IdentityDAO identityDAO = new IdentityFileDAO();
identityDAO.store(new Identity("id-01","testid","test@test.com" ));
List<Identity> identities = identityDAO.getAllIdentities();
//...

Source code

You can import the Source Code and see how it works in Eclipse