Records and Objects
A simple Record : Ass2s2p1.java 
|
Revisit the text file of 1.3.4. and create a special Record class, called MyRecord.java:
// The "MyRecord" class.
public class MyRecord
{
String code;
String province;
double year [] = new double [5];
//constructor
public MyRecord ()
{
}//end constructor
} // MyRecord class
Then insert and extra column containing the official 2-letter provincial codes ( use NU for Nunavut) and read the file with the following program (make sure both programs are saved in the same directory)
NF Newfoundland and Labrador 545.3 540.9 537.9 533.8 531.6
PE Prince Edward Island 136.9 137.8 138.3 138.9 139.9
NS Nova Scotia 936.1 941.2 942.3 942.9 944.8
NB New Brunswick 753.3 755.5 755.6 756 756.7
QC Quebec 7323.6 7351.2 7381.8 7417.7 7455.2
ON Ontario 11387.4 11527.9 11697.6 11894.9 12068.3
MB Manitoba 1137.9 1142.5 1146.4 1149.1 1150.8
SK Saskatchewan 1024.9 1025.6 1022 1017.1 1011.8
AB Alberta 2906.8 2959.6 3009.9 3059.1 3113.6
BC British Columbia 3997.1 4028.3 4060.1 4101.6 4141.3
YK Yukon 31.5 31.1 30.6 30.2 29.9
NT Northwest Territories 41.1 41 40.8 41.2 41.4
NU Nunavut 26.4 26.9 27.5 28.1 28.7
|
// The "Ass2s2p1" class.
import java.awt.*;
import java.io.*;
import hsa.TextConsole;
public class Ass2s2p1
{
static TextConsole cs = new TextConsole ();
static MyRecord list [] = new MyRecord [13]; //create a new array
public static void main (String [] args) throws IOException
{
readText ("population.txt");
cs.print ("enter a provincial code: ");
String c = cs.readLine ();
int location = -1;
for (int i = 0 ; i < 13 ; i++)
if (c.equalsIgnoreCase (list [i].code))
location = i;
if (location > -1)
{
cs.println("Population expressed in thousands");
cs.println ("Province 1998 1999 2000 2001 2002");
cs.print (list [location].province, 25);
for (int i = 0 ; i < 5 ; i++)
cs.print (list [location].year [i], 10, 1);
cs.println ();
}
} // main method
public static void readText (String fileName) throws IOException
{
String line;
FileReader f = new FileReader (fileName);
BufferedReader input = new BufferedReader (f);
MyRecord prov;
for (int i = 0 ; i < 13 ; i++)
{
prov = new MyRecord (); // create space for a new record
line = input.readLine ();
prov.code = line.substring (0, 2);
prov.province = line.substring (3, 30).trim ();
prov.year [0] = Double.valueOf (line.substring (30, 40)).doubleValue ();
prov.year [1] = Double.valueOf (line.substring (40, 50)).doubleValue ();
prov.year [2] = Double.valueOf (line.substring (50, 60)).doubleValue ();
prov.year [3] = Double.valueOf (line.substring (60, 70)).doubleValue ();
prov.year [4] = Double.valueOf (line.substring (70)).doubleValue ();
list [i] = prov;
} // end i-loop
input.close ();
} // end readText
} // Ass2s2p1 class
|
The Population Record: Ass2s2p2.java 
|
It is bad OOP practice to let another program directly access one's data. It is standard practice to have methods deal with this.
Create a new Record class called PopRecord, and add methods that will pass the information to and from the record, e.g.:
public void putCode(String c)
{
code = c;
}
public String getCode(String c)
{
return code;
}
Then modify problem 2.2.1 appropriately:
Replace for example
prov.code= line.substring(0,2);
by: prov.putCode(line.substring(0,2));
|
// The "Ass2s2p2" class.
import java.awt.*;
import java.io.*;
import hsa.TextConsole;
public class Ass2s2p2
{
static TextConsole cs = new TextConsole ();
static PopRecord list [] = new PopRecord [13]; //create a new array
public static void main (String [] args) throws IOException
{
readText ("population.txt");
cs.print ("enter a provincial code: ");
String c = cs.readLine ();
int location = -1;
for (int i = 0 ; i < 13 ; i++)
if (c.equalsIgnoreCase (list [i].getCode ()))
location = i;
if (location > -1)
{
cs.println ("Province 1998 1999 2000 2001 2002");
cs.print (list [location].getName (), 25);
for (int i = 1998 ; i < 2003 ; i++)
cs.print (list [location].getYear (i), 10, 1);
cs.println ();
}
} // main method
public static void readText (String fileName) throws IOException
{
String line;
FileReader f = new FileReader (fileName);
BufferedReader input = new BufferedReader (f);
double pop;
PopRecord prov;
for (int i = 0 ; i < 13 ; i++)
{
prov = new PopRecord (); // create space for a new record
line = input.readLine ()+" ";
prov.putCode (line.substring (0, 2));
prov.putName (line.substring (3, 30).trim ());
for (int yr = 0 ; yr < 5 ; yr++)
{
pop = Double.valueOf (line.substring (30 + yr * 10, 40 + yr * 10)).doubleValue ();
prov.putYear (yr + 1997, pop);
}
list [i] = prov;
} // end i-loop
input.close ();
} // end readText
} // Ass2s2p2 class
|
A File Reading Object: Ass2s2p3.java 
|
Convert the filereading method to a separate class also with
constructor ReadProvPops( String filename)
and one extra method: PopRecord getOne (int i) that will pass on to the main program the i-th record.
|
The ReadProvPops Class
This class will load the entire text file into an array of records, when instantiated.
The method PopRecord getOne(int i) will pass the ith record to the calling program.
// The "ReadProvPops" class.
import java.io.*;
public class ReadProvPops
{
private PopRecord list [];
private final int FILELEN=13;
public ReadProvPops (String fileName) throws IOException
{
list=new PopRecord [FILELEN];
String line;
FileReader f = new FileReader (fileName);
BufferedReader input = new BufferedReader (f);
double pop;
PopRecord prov;
for (int i = 0 ; i < FILELEN ; i++)
{
prov = new PopRecord (); // create space for a new record
line = input.readLine () + " ";
prov.putCode (line.substring (0, 2));
prov.putName (line.substring (3, 30).trim ());
for (int yr = 0 ; yr < 5 ; yr++)
{
pop = Double.valueOf (line.substring (30 + yr * 10, 40 + yr * 10)).doubleValue ();
prov.putYear (yr + 1997, pop);
}
list [i] = prov;
} // end i-loop
input.close ();
} // end constructor
public PopRecord getOne (int i)
{
if (i > -1 && i < FILELEN)
return list [i];
return null;
}// end getOne
} // ReadProvPops class
|
The PopRecord Class
Each record has this format: a code, a name and 5 double type data items
// The "PopRecord" class.
public class PopRecord
{
private String code;
private String name;
private double year [] = new double [5];
//constructor
public PopRecord ()
{
}
public void putCode (String c)
{
code = c;
}
public void putName (String n)
{
name = n;
}
public void putYear (int y, double p)
{
if (y > 1997 & y < 2003)
year [y - 1998] = p;
}
public String getCode ()
{
return code;
}
public String getName ()
{
return name;
}
public double getYear (int y)
{
if (y > 1997 & y < 2003)
return year [y - 1998];
return 0;
}
} // PopRecord class
|
The Calling Program
// The "Ass2s2p3" class.
import java.awt.*;
import java.io.*;
import hsa.TextConsole;
public class Ass2s2p3
{
static TextConsole cs = new TextConsole ();
static PopRecord prov = new PopRecord ();
static ReadProvPops file;
public static void main (String [] args) throws IOException
{
file = new ReadProvPops ("population.txt");
cs.print ("enter a provincial code: (enter an invalid one to stop) ");
String c = cs.readLine ();
int here = locationFromCode (c);
while (here != -1)
{
prov = file.getOne (here);
cs.println ("Province 1998 1999 2000 2001 2002");
cs.print (prov.getName (), 25);
for (int i = 1997 ; i < 2002 ; i++)
cs.print (prov.getYear (i), 10, 1);
cs.println ();
cs.print ("enter a provincial code: (enter an invalid one to stop) ");
c = cs.readLine ();
here = locationFromCode (c);
} //end while
cs.println("bye");
} // main method
public static int locationFromCode (String code)
{
for (int i = 0 ; i < 13 ; i++)
if (code.equalsIgnoreCase (file.getOne (i).getCode ()))
return i;
return -1;
} //end locationFromCode
} // Ass2s2p3 class
|
Creating a Binary File: Ass2s2p4.java 
|
Write a program that will convert this text file into a binary file. Allocate 30 bytes for the city's name, and 8 each for the double year values for a total of 70 bytes each record. Use the length() method to find the total length of the file.
cities.txt to be converted to cities.dat
Toronto (ON) 4586.7 4673.3 4773.6 4907 5029.9
MontrÈal (QC) 3423.9 3449.2 3479.4 3511.4 3548.8
Vancouver (BC) 1998.4 2028.9 2060.7 2099.4 2136.2
Ottawa-Hull (ON-QC) 1055.6 1069 1087.3 1108.5 1128.9
Calgary (AB) 903.1 926.2 947.9 969.6 993.2
Edmonton (AB) 914.4 928.1 941.8 954.1 967.2
QuÈbec (QC) 686.6 688.5 690.8 694 697.8
Winnipeg (MB) 677.8 679.9 682.4 684.3 685.5
Hamilton (ON) 657.8 664.8 672.1 680 686.9
London (ON) 416 418.6 422.3 425.2 427.3
Kitchener (ON) 408.5 415.8 423.8 431.2 438
St. Catharines-Niagara (ON) 387.5 388.8 390.8 391.9 392.3
Halifax (NS) 348.9 353.4 356 359.1 363.2
Victoria (BC) 316.8 316.9 317.1 319.4 322.1
Windsor (ON) 295.9 300.6 307 313.7 319.9
Oshawa (ON) 287.5 292.5 298.9 304.6 310
Saskatoon (SK) 229.5 230.7 231 231.5 231.8
Regina (SK) 199.2 199.8 199.3 198.3 197
St. John's (NF) 175.2 175.4 176.2 176.4 177.2
Chicoutimi-JonquiËre (QC) 162.6 161.8 160.3 158.8 156.9
Sudbury (ON) 162 159.3 157.7 157 155.9
Sherbrooke (QC) 152.3 152.7 153.8 155 156.5
Trois-RiviËres (QC) 141.9 141.8 141.6 141.2 141.4
Thunder Bay (ON) 127.5 126.9 125.9 125.7 125.1
Saint John (NB) 127.5 127.7 127.7 127.3 127
|
// The "Ass2s2p4" class.
import java.awt.*;
import java.io.*;
import hsa.TextConsole;
public class Ass2s2p4
{
static TextConsole cs = new TextConsole ();
static PopRecord prov = new PopRecord ();
static ReadProvPops file;
public static void main (String [] args) throws IOException
{
file = new ReadProvPops ("population.txt");
RandomAccessFile f = new RandomAccessFile ("population.dat", "rw");
for (int i = 0 ; i < 13 ; i++)
{
prov = file.getOne (i);
byte codeBytes [] = new byte [2];
prov.getCode ().getBytes (0, 2, codeBytes, 0);
f.write (codeBytes);
byte nameBytes [] = new byte [28];
// add an extra 28 spaces to assure that there are at least 28
String temp = prov.getName () + " ";
temp.getBytes (0, 28, nameBytes, 0);
f.write (nameBytes);
for (int yr = 1998 ; yr < 2003 ; yr++)
f.writeDouble (prov.getYear (yr));
} //end for each record
cs.println ("there are a total of " + f.length () + " bytes in the file");
cs.println ("13 records each holding " + f.length () / 13 + " bytes each");
f.close ();
} // main method
} // Ass2s2p4 class
|
A Binary File Manager: CityFile.java 
|
When instantiated, the CityFile will open the file, and makes available 3 methods:
- CityRecord getCityRecord (int i) which returns the ith record
- void putCityRecord (CityRecord rec, int i) which saves a record in the ith place
- long getLength () which returns the total number of records in the file.
|
// The "CityFile" class.
import java.io.*;
public class CityFile
{
private RandomAccessFile f;
private CityRecord r;
private long len = 0;
private long fileLen = 0;
private long current = 0;
private String fileName;
public CityFile (String fileName) throws IOException
{
this.fileName = fileName;
f = new RandomAccessFile (fileName, "rw");
fileLen = f.length ();
len = fileLen / 70;
} // end constructor
public CityRecord getCityRecord (int i) throws IOException
{
CityRecord r = new CityRecord ();
current = i;
if (i > len)
current = len - 1;
if (i < 0)
current = 0;
f.seek ((long) current * 70);
byte codeBytes [] = new byte [30];
f.readFully (codeBytes);
String name = new String (codeBytes, 0).trim ();
r.putName (name);
for (int yr = 1998 ; yr < 2003 ; yr++)
{
double tempDouble = f.readDouble ();
r.putYear (yr, tempDouble);
}
return r;
} //end getCityRecord
public void putCityRecord (CityRecord rec, int i) throws IOException
{
current = i;
if (i > len)
current = len;
if (i < 0)
current = 0;
f.seek ((long) current * 70);
String name = rec.getName () + " ";
f.writeBytes (name.substring (0, 30));
for (int yr = 1998 ; yr < 2003 ; yr++)
f.writeDouble (rec.getYear (yr));
f.close ();
f = new RandomAccessFile (fileName, "rw");
len = f.length () / 70;
} //end putCityRecord
public long getLength ()
{
return len;
}
} // CityFile class
|
Reading from a Binary File: Ass2s2p5.java 
|
Create a program that will let you read from from the binary file (see cities.dat below) and print out any record, given a record number: 1 for Toronto, 6 for Edmonton, etc.
|
// The "Ass2s2p5" class.
import java.awt.*;
import java.io.*;
import hsa.TextConsole;
public class Ass2s2p5
{
static TextConsole cs = new TextConsole ();
static CityRecord cityRec = new CityRecord ();
static CityFile f;
public static void main (String [] args)throws IOException
{
f= new CityFile ("cities.dat");
long len = f.getLength ();
cs.print ("enter a number between 0 and " + (len - 1) + " (negative to stop): ");
int location = cs.readInt ();
while (location >= 0)
{
cityRec = f.getCityRecord (location);
cs.println ("Population expressed in thousands");
cs.println ("City 1998 1999 2000 2001 2002");
cs.print (cityRec.getName(), 30);
for (int y = 1998 ; y < 2003 ; y++)
cs.print (cityRec.getYear (y), 10, 1);
cs.println ("\n");
cs.print ("enter a number between 0 and " + (len - 1) + " (negative to stop): ");
location = cs.readInt ();
}
cs.println("bye!");
} // main method
} // Ass2s2p5 class
|
Writing to a Binary File: Ass2s2p8.java 
|
Write a program that lets you add data to the Cities.dat file. Then add the populations of:
Iqaluit (Nunavut), population: 4.4, 4.6, 4.8, 5.0, 5.2
Yellowknife (NT) population: 17.2, 17.1, 16.9 , 16.7 , 16.5
Charlottetown (PE) population: 32.5, 32.4, 32.3. 32.2, 32.2
|
// The "Ass2s2p8" class.
import java.awt.*;
import java.io.*;
import hsa.Console;
public class Ass2s2p8
{
static Console cs = new Console ();
static CityRecord cityRec = new CityRecord ();
static CityFile f;
public static void main (String [] args) throws IOException
{
f = new CityFile ("cities.dat");
long len = f.getLength ();
cs.print ("Enter the name of a new city or \"stop\" to stop: ");
String name = cs.readLine ();
while (!name.equalsIgnoreCase ("stop"))
{
cityRec.putName (name);
for (int y = 1998 ; y << 2003 ; y++)
{
cs.print ("enter the population in " + y + "in thousands: ");
double pop = cs.readDouble ();
cityRec.putYear (y, pop);
}
cs.print ("\nis this correct? (y or n): ");
String c = cs.readString ();
if (c.charAt (0) == 'y' || c.charAt (0) == 'Y')
{
f.putCityRecord (cityRec, (int) f.getLength ());
cs.println ("successfully recorded");
}
else
cs.println ("record data ignored");
cs.print ("Enter the name of a new city or \"stop\" to stop: ");
name = cs.readLine ();
}
cs.println ("bye!");
} // main method
} // Ass2s2p8 class
|
|
Sponsored by ECOO and SIG-Computer Science
.
|
|
|