/** * Converts cashflow.txt to cashflow.dat for the current account balances applet cashflow.class * @author Robert J Morton UK-YE572246C * @version 09 July 2000 */ /* This program uses the Java 1.1.8 API. This program accepts input from a text file called savyyyy.txt where yyyy is the year number eg 1997, 1998, 1999, 2000. Enter this file name as a command line argument so that command line looks like: java savlim0 sav1998.txt If you don't enter an input file argument, this program will assume it is in savlim.txt The format of this imput text file should be like this: 01JAN98 2345.48 442.34 02 03 2335.48 04 05 432.34 Rules: 1) The file contains a line for each day of the year concerned, namely 365 or 366 lines. 2) The first of each month is entered as shown above. 3) Subsequent days of the month can have just the number. 4) This must be two-digits, ie with a leading zero for 1 to 9 5) All days must be present whether or not it contains money fields 6) Where no financial data appears on a line, the date should be followed immediately by a '\n' 7) Where present, the first money field is the balance in my current account on that day 8) Where present, the 2nd money field is the balance in Ruby's current account on that day 9) A '\t' (tab-character) must separate any balance in my account shown 10) A further '\t' must separate any balance shown for Ruby's account 11) Where only a balance for Ruby's account is shown, two tabs must separate it from the date 12) Either balance need be entered only on the dates on which it changes This program generates a data file with the same file name as the input file, but with the extension .dat instead of .txt, eg: cf1998.dat This output file contains a stream of 32-bit binary integers, two per day. It is the input file for the presentation applet savlim1.class This output file must be placed on the web server in the same directory as cf.class. This is in fact the directory for Chapter 6 of The Lost Inheritance: /book/chap06/ */ import java.io.*; class savlim0 { public static void main(String args[]) throws IOException { String fn; int c = '.'; // dot between file name and extension /* Try to find position of dot and thereby isolate the naked file name. In the event of an exception set the default file name. */ try {fn = args[0]; int x = fn.lastIndexOf(c); fn = fn.substring(0, x);} catch(ArrayIndexOutOfBoundsException e) { fn = "savlim"; } BufferedReader r = new BufferedReader( new InputStreamReader( new FileInputStream(fn + ".txt") ) ); DataOutputStream w = new DataOutputStream( new FileOutputStream(fn + ".dat") ); String s; int x = 0, y = 0, // rob's balance, ruby's balance i = 0, j = 0, // tab markers l = 0, // length of input line d = 0; // number of days accumulator double t = 0; c = '\t'; // tab character for testing while((s = r.readLine()) != null) { // read in the next line of text if((l = s.length()) > 1) { // if there is a valid entry on this line // if at least one tab exists, we have to update something if((i = s.indexOf(c)) != -1) { i++; // 'i' points to first char of first field /* If the second tab exists, there are two fields, so if there is anything in my balance field, update rob and if the line extends beyond second tab, update Ruby's balance. Else [if the second field does not exist], update rob only. */ if((j = s.indexOf(c, i)) != -1) { if(j > i) x = scale(s.substring(i,j)); if(l > j) y = scale(s.substring(j + 1)); } else if(l > i) x = scale(s.substring(i)); } // end of 'if at least one tab exists' // Write mine and Ruby's balances to file and to terminal. w.writeInt(x); w.writeInt(y); System.out.println("" + x + " " + y); d++; t += (double)(x + y); } else { // Else the line is too short to contain w.writeInt(-1); // a vanid entry, so write a null entry w.writeInt(-1); // to each file. } } // Write the average to the terminal and close the files. System.out.println("Average " + (t / (100 * d))); w.close(); r.close(); } static int scale(String s) { //returns an integral number of pence double f = Double.valueOf(s).doubleValue(); return (int)Math.round(f * 100); } }