School Locker Database - a Mini-project with RandomAccessFile
Our school has lockers - one for each student in grades 6-12. Each homeroom teacher keeps track of the locker assignments by writing them on a sheet of paper.
Before starting to write the program, you should do a more extensive investigation. You should try to answer most of the following questions:
- How many lockers are
there?
- How are they
numbered?
- Do any lockers have 2
students assigned?
- Do any students have 2
lockers?
- Are the combinations written
down?
- Who is "in charge" of the
lockers?
- Are there problems with the
current system that can be handled better using a computer
program?
- It's good to collect some sample
documents - e.g. a homeroom teacher's paper
list
People's Tasks
What tasks must the people (e.g. teachers, administrators) perform? For example:
- Assign a set of lockers to a
homeroom teacher
- Assign a locker to a
student
- Assign a locker to a new student, by first
finding an empty locker
- Unassign a locker when a
student leaves the school.
- Open a locker in an
emergency
- ... more tasks ... especially any new
tasks to be performed differently in the computerized
version
What algorithms should the program be able to perform? These must adequately support the tasks listed above.
- Input and record a name for a
locker
- Erase the name from an assigned locker
(unassign)
- Find the number of an empty
locker
- Search for a particular name and print the
corresponding locker number
- Print out all the
assigned locker numbers with names
- Sort the list of
assigned lockers alphabetically
- Save all the names
and other data in a file on the disk drive
- ... more
algorithms ...
The investigation turned up that there are two sets of lockers - one set for the middle school (on the first floor) and another set for the high school (on the second floor). Both sets start counting at #1. So the representation will need to make a distinction. They could be called 1001, 1002, ... for the middle school and then 2001, 2002, ... for the high school. This allows all lockers to be saved in a single list with no confusion.
The list can be stored in a 2-D array, like this:
|
Row |
Name |
Homeroom |
Combination |
|---|---|---|---|
|
1001 |
Luke, Lucky |
Mr Smith |
1-1-1 |
The LAST step is to consider the interface. This sits in the center of everything, connecting the user to the algorithms. The interface must contain appropriate controls for doing data input/output and to allow the user to control the program. A very, very simple interface will be used in the feasibility prototype below, supporting only a small part of the actual requirements:

// a simplified program to check that storing in a 2-D array will work properly //
import java.awt.*;
// contains GUI controls
import java.io.*;
// contains data-file commands -
for later
public class Lockers extends
EasyApp
{
public static void main(String[] args)
{ new Lockers(); }
Button bClear = addButton("Clear All",50,50,100,50,this);
Button bAssign = addButton("Assign",150,50,100,50,this);
Button bShowNames = addButton("Show Names",250,50,100,50,this);
String[][] list =
new
String[3000][3];
// 3 columns for name, HR,
combination
public Lockers()
{ setSize(400,150);
setTitle("Lockers Database");
}
public void actions(Object source,String command)
{
if (source ==
bClear)
{
clearList(); }
else if (source ==
bAssign)
{
assignLocker(); }
else if (source ==
bShowNames)
{
showNames(); }
}
public void clearList() // Fills array with empty
Strings
{
for (int
row
= 0;
row
< 3000;
row
=
row+1)
{
for (int
col
= 0;
col
< 3;
col
=
col+1)
{
list[row][col] =
"";
}
}
}
public void
assignLocker() //
Put student name into list
{
String name = input("Type the name of the student");
int locker = inputInt("Type the locker number:");
list[locker][0]
=
name;
}
public void showNames() // Show non-blankc names and
lockers
{
for (int
row
= 0;
row
< 3000;
row
=
row
+ 1)
{
if ( !list[row][0].equals("")
)
{ System.out.println(row + "\t" + list[row][0]);
}
}
}
}
This
diagram shows that a computer system is a lot more than just the program, so developers
must pay attention to a lot more pieces than
programmers.

After
the initial idea, and a very simple prototype program, we need to talk to
the intended user.
That would be the vice principal(s).
A sophisticated computer user might tell you exactly what they need. Most users aren't that logical, so you need to have an active conversation with them - asking questions, suggesting solutions, recording all the ideas ON PAPER (or in your computer if you have one along).
Most users respond well to requests for stories (scenarios). For example:
You ask: "Do students ever forget their combination?"
User says: "Only a few kids. But they come all the time. There's one kid that is in here at least once a week. I don't look up his combination [on the sheets] any more - I've memorized it."
You ask: "How often do you need to look up a combination?"
User says: "I don't know, maybe a couple times each week."
You ask: "Would you rather do that with a computer than with paper sheets?"
User says: "Not really. But I'd rather that the kid could ask their homeroom teachers - they have a copy of the paper. But if I'm not in the office and the kid can't find the teacher - will the kids be able to access this database?"
You say: "Well, then they could see everyone's combination. I guess we could give them passwords."
User says: "Isn't that a lot of trouble?"
You say: "How about the secretaries? We could give them access."
User says: "Yeah, that's a good idea. They're always at their desks, at least one of them anyway."
The conversation above can be summarized in a story (scenario / use-case):
A student has forgotten their combination. They go to the VP to ask him to look it up, but he isn't available. So they look for their HR teacher, but she isn't available either. So they are stuck and cannot get books out of their locker. They should be able to ask the secretary.
This leads to a need:
Student can retrieve lost combination by talking to the VP, HR teacher or secretary
This leads to several goals:
(a) Combinations are stored in the data file.
(b) The program and the data file(s) are available to several people - VP, HR teacher, secretary
(c) Combinations are only available to the "trusted" people in (b) - not directly to students
This leads to some thoughts about how to do this:
(a) Data file contains: locker number , name , combination
(b) Data file(s) and program are stored on a central server
(c) Files and program have protected access via log-in passwords
** Caution ** Remember, you cannot do everything. Sometimes you need to say "no" to the user, when they ask for something that is silly, useless, or impossible, e.g.:
User : "Can you make a program control the locker's locks directly, like those plastic cards you get for hotel rooms?"
You say : "No, we can't do that. We'd need to wire all the lockers - I don't know how to do that."
User says : "Ahhh, too bad, but that's okay."
More questions and answers and stories will lead to a long list of goals. The following summarizes some goals for this program (the stories are not shown here) :
|
Need (task) |
Goals (interface) |
How (algorithms/data structures) |
|
Store data centrally |
Store locker#, name, |
Use RandomAccessFile, one record for each locker |
|
Assign lockers |
[Add button] |
Input boxes for #, name, combination |
|
Find name & combination |
Search method |
Loop through all records |
|
Find many people, for example in same family |
Sorted list of all people |
Load records into an array |
|
Find an empty locker for a new student |
Show list of all empty lockers |
Loop through all records |
|
Erase a name from a locker |
[Delete button] |
Input name |
(In a real application, this list would be a lot longer, but we are just practicing)
A prototype is a simple, preliminary version of the program. There are two reasons for a prototype:
The prototype should not attempt to implement all of the goals. Rather, it should concentrate on the most significant user-interface and algorithm/data-structure features. For example, the big TextArea and the RandomAccessFile are more significant than the [Delete] button.
The program above is not really enough. It needs to be expanded. We will expand it as follows:
This is sufficient to check that the RandomAccessFile storage will work and to show the user more or less what we are planning.
We produced a preliminary prototype for the lockers database, to show how to store the names and homeroom teachers in a 2-D array. We noticed it is pretty annoying to type in test data every time we run the program. Some students found it difficult to do the testing for this reason, and naturally did a poor job of testing as a result.
In a real application, the data needs to be stored permanently. This is called data persistence - the data continues to exist when the program shuts down. The data needs to be saved in a data-file on the hard-disk.
One way to do this is to write the entire array into a sequential text file (BufferedReader, PrintWriter). This method would be quite acceptable, except for one small danger - if the user forgets to save the data, or if the program crashes before saving, a lot of data could be lost.
A more robust solution is to use a RandomAccessFile. In a RandomAccessFile, each new piece of data can be written directly to the file when it is entered - this is called direct access. Then if the program crashes, the data is already saved. This provides high levels of persistence (data stays) and robustness (reliability).
A RandomAccessFile can be broken up into records corresponding to the rows in an array. Each record is broken up into fields, corresponding to the columns in a 2-D array. Rather than using an index value to find a row in an array, the program must seek to a position in the file in order to read or write a record.
In the file shown below, each record occupies 75 bytes, and contains 3 fields: 32 bytes for the student name, 32 bytes for the homeroom teacher, and 11 bytes for the combination. The apostrophes ` represent blank spaces (so we can see them). The ## signs represent 2 bytes that Java uses to store the length of the UTF String. This is managed automatically, so the programmer needn't worry about it. Since 32 bytes are available, each String is limited to 30 characters so the ## bytes also fit in the field.
|
##Chaplin, Charlie``````````````##Mr
Smith``````````````````````##11-12-13` |
It appears that the third record is empty, indicating an unassigned locker. The combination for the 4th locker is blank - maybe the student doesn't have a lock.
The programmer must be careful that strings are small enough to fit in the available space. It appears that Schwarzenegger's name was truncated (the 'd' in "Arnold" is missing) so that it fits in the 30 character limit. If the String is not shortened before writing, it will run off the end of the field and destroy the data in the next field. This is called a buffer over-run. Many Trojan Horse attacks use buffer overruns to crash an operating system so they can take control of the computer. In a data-file, a buffer overrun won't cause a system crash, but could destroy data.
The following commands assign the 3rd locker to "Mike Earbyter". It uses readUTF to check whether the 3rd locker is actually free before writing into that record.
|
try |
Each field is written using a seek
command followed by writeUTF. The seek command must tell the
exact
position in the file by calculating bytes. Notice that
the records are numbered starting with 0 (zero), not starting with 1. Also
notice that file access can cause an IOException, and this must be handled by
the algorithm. One interesting "feature" is that if a
record number is
larger than the actual file, Java will automatically make the file
bigger to accommodate the command. This prevents indexOutOfBoundsExceptions like you get in an
array. But a typing mistake could cause the size of the file to
become very large, possibly filling up the entire hard-disk. That could be bad,
so the program below checks that the locker number is
smaller than 3000
before writing anything.
The program below is a simple prototype for a persistent Lockers database. You should copy the code into a Java file and get it running, and check that it correctly saves the data after the program ends.
|
|