Responsive Ad Area

Share This Post

Blog Role / Java

Reading and Writing delimited files using Java

Prev post in this trail is Reading and Writing files using Java
Next post in this trail is Reading and Writing Property Files using Java

Next we will want to be able to get data from a text file. Java has some basic data types.

  • String
  • int
  • float
  • boolean

And after that

  • byte
  • short
  • long
  • double
  • char

And we will use the Date object which is deprecated but we will use it anyway in this example.

We have already worked with single line strings in part 1. We can store one data type per line or more than one data type per line. There are different ways to do this. Its helpful if we know an order for the data types being stored. For example you could store a file of a single data type so that each line is say an int or float. But generally you want different types of data in the same file. And generally in a record format. A record being a list of data types in a certain order. For example. A expense tracking record might be.

  • Date
  • Expense Note
  • Amount

An address book might be.

  • Name
  • Addresss
  • City
  • State
  • Zip

We could simple put each data type on one line in the file and add record after record one after another. This might be a simpler coding but its not easy to read or edit as a text file. An xml file would be nice here but we are not working with xml at the moment. A delimited file works better for this application. And there are different ways to delimit a file. I like pipe delimited using | symbol. also , delimited is common or "," delimited.

Pipe Delimimted
10/2/18|Coke Vending|1.75
10/3/18|Steak Meal|17.52
10/4/18|Gas for Van|54.13

Comma Delimited
10/2/18,Coke Vending,1.75
10/3/18,Steak Meal,17.52
10/4/18,Gas for Van,54.13

Quote Comma Delimited
"10/2/18","Coke Vending","1.75"
"10/3/18","Steak Meal","17.52"
"10/4/18","Gas for Van","54.13"

Another way we might store data is name value pairs. Java Properties class does this for us. But for example purposes I will code this myself. Commonly state or configuration data is stored this way. Or maybe statistics for a report. Or lets say we have a video game.

userName=John
password=1234abcd
money=1125.25
level=5;
magic=false;

And yet another interesting way that is probably not typical is row and column based storage like a spreadsheet. This could be good for storing reports or statics.

Expense|Amount|Food|5.32||
||Gas|45.22||
||Hair Cut|15.23|Weekly|Monthly
||Total|65.77|235.12|2334.23

The source below simply demonstrates how to parse the lines of the file.

import java.io.*;
import java.util.regex.*;

public class AFileReader {
 private static String aFileName = "textfile1.txt";
 public static void main(String[] args) {
  try (BufferedReader br = new BufferedReader(new FileReader(aFileName))) {
   String aLine;
	while ((aLine = br.readLine()) != null) {
	 String[] dataRecord=aLine.split(Pattern.quote("|"));
	 for(int i=0;i<dataRecord.length;i++)
	  System.out.println(dataRecord[i]);
	}
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
}

Next we will convert the same data from strings to given data types and output the results. I also added a couple of fields.

10/2/18|Coke Vending|1.75|100|true
10/3/18|Steak Meal|17.52|102|false
10/4/18|Gas for Van|54.13|508|true

Next we parse the delimited lines and rebuild as output without the pipes. After this we will save the data back to disk file.
This sets us up for altering and adding to the data and saving.

import java.io.*;
import java.util.regex.*;
import java.util.*;
import java.text.*;

public class AFileReader {
 private static String aFileName = "textfile1.txt";
 public static void main(String[] args) {
  Date date=null;
  String note="";
  float amount=0.0f;
  int account=0;
  boolean active=false;
  SimpleDateFormat dateFormat=null;
  try (BufferedReader br = new BufferedReader(new FileReader(aFileName))) {
   String aLine;
	while ((aLine = br.readLine()) != null) {
	 String[] dataRecord=aLine.split(Pattern.quote("|"));
	 for(int i=0;i<dataRecord.length;i++){
	  if(i==0) date=new Date(dataRecord[i]);
	  if(i==1) note=dataRecord[i];
	  if(i==2) amount=Float.parseFloat(dataRecord[i]);
	  if(i==3) account=Integer.parseInt(dataRecord[i]);
	  if(i==4) active=Boolean.parseBoolean(dataRecord[i]);
	 }
	  dateFormat = new SimpleDateFormat("dd/MM/yy");
	System.out.println(dateFormat.format(date)+" "+note+" "+amount+" "+account+" "+((active)?"Active":"Not Active"));
	}
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
}

02/10/18 Coke Vending 1.75 100 Active
03/10/18 Steak Meal 17.52 102 Not Active
04/10/18 Gas for Van 54.13 508 Active

Next we read it in and write it back out to different file to show that it indeed worked. Though you would see that it worked if written to the same file in this case because in the original file the date was written as 10/2/18 and in the output file 10/02/18 with leading 0 on day.

import java.io.*;
import java.util.regex.*;
import java.util.*;
import java.text.*;

public class AFileReaderWriter {
 private static String aFileName = "textfile1.txt";
 private static String outputFileName = "textfile2.txt";
 public static void main(String[] args) {
  String aLine=null;
  ArrayList<String> lines=new ArrayList<String>();
  Date date=null;
  String note="";
  float amount=0.0f;
  int account=0;
  boolean active=false;
  SimpleDateFormat dateFormat=null;
  try (BufferedReader br = new BufferedReader(new FileReader(aFileName))) {
  
	while ((aLine = br.readLine()) != null) {
	 String[] dataRecord=aLine.split(Pattern.quote("|"));
	 for(int i=0;i<dataRecord.length;i++){
	  if(i==0) date=new Date(dataRecord[i]);
	  if(i==1) note=dataRecord[i];
	  if(i==2) amount=Float.parseFloat(dataRecord[i]);
	  if(i==3) account=Integer.parseInt(dataRecord[i]);
	  if(i==4) active=Boolean.parseBoolean(dataRecord[i]);
	 }
	 dateFormat = new SimpleDateFormat("MM/dd/yy");
	 aLine=dateFormat.format(date)+"|"+note+"|"+amount+"|"+account+"|"+active+"\n";
	 lines.add(aLine);
	}
   } catch (IOException e) {
    e.printStackTrace();
   }
   AFileReaderWriter frw= new AFileReaderWriter();
   frw.write(lines);
  } 
  public void write(ArrayList<String> lines) {
   try (BufferedWriter bw = new BufferedWriter(new FileWriter(outputFileName))) {
    Iterator<String> linesIterator = lines.iterator();
    while(linesIterator.hasNext())
     bw.write(linesIterator.next());
   } catch (IOException e) {
    e.printStackTrace();
   }
 }
}
10/02/18|Coke Vending|1.75|100|true
10/03/18|Steak Meal|17.52|102|false
10/04/18|Gas for Van|54.13|508|true

Next we could make an object to hold each records data and to convert it to a line and use an ArrayList of this object. Should we call it RecordSet? Naw how about ExpenseRecord.

import java.io.*;
import java.util.regex.*;
import java.util.*;
import java.text.*;

public class RecordReaderWriter {
 private static String aFileName = "textfile1.txt";
 private static String outputFileName = "textfile3.txt";
 public class ExpenseRecord{
  Date date=null;
  String note="";
  float amount=0.0f;
  int account=0;
  boolean active=false;
  public String toString(){
   SimpleDateFormat dateFormat=null;
   dateFormat = new SimpleDateFormat("MM/dd/yy");  
   return dateFormat.format(date)+"|"+note+"|"+amount+"|"+account+"|"+active+"\n";
  }
 }
 public static void main(String[] args) {
  String aLine=null;
  RecordReaderWriter rrw = new RecordReaderWriter();
  ArrayList<ExpenseRecord> records=new ArrayList<ExpenseRecord>();
  try (BufferedReader br = new BufferedReader(new FileReader(aFileName))) {
	while ((aLine = br.readLine()) != null) {
	 String[] dataRecord=aLine.split(Pattern.quote("|"));
	 ExpenseRecord expense= rrw.new ExpenseRecord();
	 for(int i=0;i<dataRecord.length;i++){
	  
	  if(i==0) expense.date=new Date(dataRecord[i]);
	  if(i==1) expense.note=dataRecord[i];
	  if(i==2) expense.amount=Float.parseFloat(dataRecord[i]);
	  if(i==3) expense.account=Integer.parseInt(dataRecord[i]);
	  if(i==4) expense.active=Boolean.parseBoolean(dataRecord[i]);
	 }	 
	 records.add(expense);
	}
   } catch (IOException e) {
    e.printStackTrace();
   }
   rrw.write(records);
  } 
  public void write(ArrayList<ExpenseRecord> expenseRecords) {
   try (BufferedWriter bw = new BufferedWriter(new FileWriter(outputFileName))) {
    Iterator<ExpenseRecord> expenseRecordsIterator = expenseRecords.iterator();
    while(expenseRecordsIterator.hasNext())
     bw.write(expenseRecordsIterator.next().toString());
   } catch (IOException e) {
    e.printStackTrace();
   }
 }
}

The next thing we could do is to move the data type parsing into the ExpenseRecord class using setters and getters. After that we could write examples of altering that data within records and rewriting the file with updates. And after that use a GUI or Web application interface to allow editing of records. Java has built in searching and sorting functions if you look for them. So we have built a simple flat file database. If your application is simple why use JDBC and sql. It could be overkill. On the other hand if you foresee a day when the application will grow to need that, this code will become unused. The data will still port easily into any database. In the next article we will work on making our own property files for storing name and value pairs. I may add articles to this one some day to include other formats as we discussed including csv, comma delimited and fixed width text files.

Prev post in this trail is Reading and Writing files using Java
Next post in this trail is Reading and Writing Property Files using Java

Share This Post

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>