Copyright © Cay S. Horstmann 2009 
This work is licensed under a Creative Commons
Attribution-Noncommercial-Share Alike 3.0 United States License.
In this lab, you will work in groups of four for the planning part (A) and in groups of two for the implementation parts (B and C)
Put the answers to the questions in each step into the lab report. Copy/paste the programs that you write in the lab.
This icon indicates optional tasks. Do those if you have time.
Roles:
A) The scribe who writes the pseudocode and the lab report
B) The code reader who reads the pseudocode aloud during simulation and updates any variables
C) The scanner who simulates a java.util.Scanner
D) The facilitator who makes sure everyone does their thing
Let's look at these numbers a little more closely. Suppose you made $400,000 per year and then got a much-deserved bonus of another $100,000. How much of that bonus were you able to keep after federal taxes in 1961? In 2003?
Note that this data is in plain text, without any fancy fonts or images. Plain text may be ugly, but it is easy to process.
Look at the data. If necessary, resize the window so that the lines don't wrap. Notice that there are 18 header lines, then a line for 1913 with 14 numbers (that lacks the percentage changes in the last two columns), then lots of lines with 16 numbers each, then the line for the current year which isn't complete.
We can ignore the month-to-month changes. All we care about is the Annual Average in column 14. The numbers are relative to the average of 1982-1984, which is 100%.
In order to translate dollar amounts from one year to another, divide by the "from year" CPI and multiply with the "to year" CPI.
How much is 1961's $100,000 in 2003?
We will start with reading the CPI data (i.e. the second data set).
In Chapter 11, you learn how to attach a Scanner to a file
or a URL on the internet.
Remember that a Scanner can read in an entire line with
nextLine or an item at a time with next,
nextInt, or nextDouble.
Write pseudocode that reads the data from ftp://ftp.bls.gov/pub/special.requests/cpi/cpiai.txt
and fills an array with the CPI values. Put the value for year
y into cpi[y - 1913]
Address the following issues:
Scanner method(s) will you call to read and
discard the header information? How many calls?Scanner method(s) will you use to read each line? Which
values do you use? Which do you discard? What do you do with the values
that you use? (I.e. where do you put them)?Your result should be a sheet of paper with pseudocode (which the scribe should add to the lab report).
Run the simulation until 1916 (to catch that blank line), then skip ahead to the current year line.
Which elements have been filled into which locations of the
cpi array as result of your simulation?
Scanner sees when
reading this data, use the "View Source" command of your browser. What do
you notice?<tr><td align="center">1913</td><td align="center">7</td><td> </td><td align="center">500,000</td></tr> <tr><td align="center">1914</td><td align="center">7</td><td> </td><td align="center">500,000</td></tr> <tr><td align="center">1915</td><td align="center">7</td><td> </td><td align="center">500,000</td></tr> <tr><td align="center">1916</td><td align="center">15</td><td> </td><td align="center">2,000,000</td></tr> ...
Let's break down our task of reading these data into three subtasks:
The line for 1913 that you will print should look like this:
1913 7 10873889
(10873889 is 500000 * 215.303 / 9.9)
What line should you print for 1944?
nextLine. Describe
which ones you should analyze further.<tr><td align="center">1914</td><td align="center">7</td><td> </td><td align="center">500,000</td></tr>
As you may know, the <td...>...</td> enclose
table cells. A worthwhile subtask is to write a method
ArrayList<String> extractTableCells(String row)
For example, with the sample input above, the result will be an
ArrayList<String> with entries
"1914" "7" " " "500,000"
This isn't really related to I/O and exceptions, so we won't spend time in this lab developing this method. It will just be given to you. But to show that you have an understanding how it works, put in your lab report what the method should return for the input line of 1944.
String objects. You don't want
strings. You want numbers. Discuss how you will convert the strings to
numbers. Discuss what challenges you will encounter. (Hint:
"500,000". The footnotes that you saw in the preceding step.)
How will you get rid of those commas? (Hint: Blast from the
past—section 2.4 of your textbook).Scanner calls do you make?extractTableCells)?extractTableCells will give you an array of four
elements. What do you do with each array element to extract the number
that may be inside it?cpi array has been correctly
initialized in step 3.extractTableCells.
The scribe reports the results of the walkthrough.
You do this part in groups of 2, using the strategies that you developed in part A.
iolab.
Click Finish. A class Main has been provided for you in the
iolab package. That's a good default. But we want to make a
class CPIConverter that deals with reading the CPI data and
converting dollar amounts from one year to another. Select the
iolab package. Right-click on the iolab package
(not the project) and select New -> Java Class, then
CPIConverter.
Add methods
public void read(String location)
{
}
public double equivalentAmount(double amount, int fromYear, int toYear)
{
return amount; // We'll fix this later
}
Add an instance variable
private double[] cpi;
Add constants
private static final int FIRST_YEAR = 1913; private static final int LAST_YEAR = 2008;
read method. First initialize
cpi with an array that can hold LAST_YEAR - FIRST_YEAR +
1 values. (Why +1?)
The book tells you how to construct a scanner from a
FileReader. But we are not reading from a file. We read from
the web, as you would expect us to do in the third millennium. Here is how
you do that in Java:
Create a URL object
URL cpiURL = new URL(location); InputStream cpiIn = cpiURL.openStream();
Then, instead of constructing a scanner from a FileReader,
construct it from the cpiIn object.
As you type names such as URL and InputStream,
get in the habit of typing Ctrl+Space towards the end of the name. Netbeans
will insert the remainder of the name for you, and more importantly, add
the import statement.
If you copy/paste the code, just move the cursor to the end of
URL and InputStream, then hit Ctrl+Space.
Try it out now!

That means that the IDE found an error with the code. Click on the
lightbulb to get “quick fix” suggestions. The quick fix that we
want is to add a throws specifier. (Do not add a
try/catch block. We will handle the exceptions elsewhere.)
Try it out. Let the IDE add the exceptions. Click on the first light
bulb and choose throws..., then on the second. The light bulbs
should go away. What code was added?
In fact, IDEs are not perfect. Look up the documentation of MalformedURLException.
Note its superclasses. Note the other class that Netbeans added to the
throws specifier. How can you simplify the throws
specifier?
read method to process it.
What is the code of your read method?equivalentAmount method. Use cpi[fromYear
- FIRST_YEAR] and cpi[toYear - FIRST_YEAR] to adjust
the amount. What is the code of your method?Main class that Netbeans made for you. In
its main method, add
CPIConverter conv = new CPIConverter();
conv.read("http://horstmann.com/sjsu/cs46a/lab12/cpiai2.txt");
double amount = 100000;
double adjusted = conv.equivalentAmount(amount, 1962, 2008);
System.out.printf("Adjusted amount: %10.0f\n", adjusted);
You will get another lightbulb. Why?
main throw the exception. We'll fix that
later. Now run your program. What value do you get? Is it the same as in
step A2?read method. A red box should appear, indicating a
breakpoint.
From the menu, choose Debug -> Debug Main Project. When the debugger stops at the line, click on the Variables tab below.

Expand the this variable until you see the cpi
instance variable. What is its value?

What is the cpi contents now?
cpi variable. What do you see? Why?Each click, one iteration of the loop is executed. What happens with the
cpi contents?
read method to implement the
strategy that you developed in step A3. Change main so that it
reads from ftp://ftp.bls.gov/pub/special.requests/cpi/cpiai.txt. Run your
program to check that it works.
What is the code of your read method now?
read method in main
to http://www.cs.sjsu.edu/foo.html. Run the program. What
happens?In which method should they be caught, read or
main?
IOException and print a suitable message to the
user. What is the code of your modified method?MalformedURLException than a garden variety
IOException. Change your method so that it prints “Whoa!
Your URL was malformed.” or “To our chagrin, an IOException has
occurred.” Also print the message stored in the exception object.
What is the code of your modified method?foo://bar.html. Run
the program again. What happens?TaxData. Add these instance
variables:
public class TaxData
{
private int year;
private double topMarginalRate;
private double topMarginalThreshold;
}
Move the cursor above the } and hit Ctrl-Space. You'll get a window such as this one.

Select the second constructor public TaxData(int year, double
topMarginalRate, double topMarginalThreshold) and hit Enter. What
happens?
getYear,
getTopMarginalRate, and getTopMarginalThreshold.
What happens?TaxTableReader
public class TaxTableReader
{
public void read(String location) throws IOException
{
}
public void print(CPIConverter conv, int year)
{
}
private ArrayList<String> extractTableCells(String row)
{
ArrayList<String> result = new ArrayList<String>();
int pos = 0;
boolean done = false;
while (!done)
{
pos = row.indexOf("<td", pos);
if (pos == -1) done = true;
else
{
pos = row.indexOf(">", pos);
int start = pos + 1;
pos = row.indexOf("</td>", pos);
result.add(row.substring(start, pos));
}
}
return result;
}
private ArrayList<TaxData> data;
}
Now write the read method.
location a line at a time, and
only process the lines in the table.
while (in.hasNextLine())
{
String line = in.nextLine();
if (line.startsWith("<tr><td align=\"center\">"))
{
...
}
}
(Note the \" because we are looking for a string
containing quotation marks: <tr><td
align="center">)
extractTableCellsindexOf(" ").
Have a look at extractTableCells if you want to see
indexOf in action.)int and two
doubleTaxData object and add it to the dataWhat is the code of your read method?
main, add code to make a
TaxTableReader and read from
http://www.truthandpolitics.org/top-rates.php. Compile and run. If your
program doesn't throw any exceptions, go on to the next step.1913 7.0 10,873,889 1914 7.0 10,765,150 1915 7.0 10,658,564 1916 15.0 39,505,138 ...
Use the converter to convert the thresholds to the given year.
To add those commas, add a comma to the printf descriptor:
%,10.0f.
What is the code of your print method?
main, call print and run
your program. What is the output?print method so that the output
is sent to a file:
public void print(String filename, CPIConverter conv, int year) throws IOException