More on Java Filesand HW #3

advertisement

Session 06

More on Java Files and HW #3

Java File I/O Example: Echo.java

• echoes all the words in one file to an output file, one per line.

$ java Echo hamlet.txt hamlet.out

$ less hamlet.out

1604 the tragedy of hamlet prince of denmark by william shakespeare ...

import java.io.*; import java.util.StringTokenizer; public class Echo { public static void main( String[] args ) throws IOException {

String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r";

BufferedReader inputFile = new BufferedReader(new FileReader(args[0]) );

PrintWriter outputFile = new PrintWriter( new FileWriter( args[1] ) );

String buffer = null; while( true ) { buffer = inputFile.readLine(); if ( buffer == null ) break; buffer = buffer.toLowerCase();

StringTokenizer tokens = new StringTokenizer( buffer, delimiters ); while( tokens.hasMoreElements() ) {

String word = tokens.nextToken(); outputFile.println( word );

} // end while

} // end while(true)...

} // end main

} // end class Echo

Working with Standard Input and

Output as Files

• Sometimes, we'd like to give the user an option of providing a file name or using standard I/O.

• We can call sort with its own file argument, or we can pipe the standard output of one program (cat hamlet.out) as the standard input to sort.

• How can we make our Java programs do the same thing?

Streams vs. Readers and Writers

• a stream is a device for transmitting or receiving a sequence of byte (8-bit) values

– emphasis on reading/writing -- not on data itself

– network and file systems are based on byte unit

• Readers and Writers use 16-bit Unicode

– useful for I/O of textual values as opposed to binary data such as images, colors, etc.

– for example, BufferedRead has readLine method

Working with Standard Input and

Output as Files

• Standard input is an instance of the

InputStream class and does not respond to readLine(), which is how we would like to grab lines of text as Strings.

• Standard output does respond to println() messages, but it is a PrintStream, which cannot be stored in a PrintWriter variable.

What can we do?

• We could write duplicate code for the four different cases. (file-file, file-stdout, stdin-file, stdin-stdout)

• Every case would look the same except for one or two lines.

• That doesn't seem to be the correct solution.

Maybe we can find a way to have them talk to objects that talk to standard input and output...

A Solution

• Let's take advantage of an object-oriented idea: We ought to be able to substitute an object with a common interface, even if somewhat different behavior, in place of one another, and let the new object fulfill the responsibilities of the replaced one.

• While BufferedReaders and PrintWriters don't know how to talk to standard input and output, respectively, we can use a translator to serve as a go-between.

• Java give us the classes we need: InputStreamReader and

OutputStreamWriter.

import java.io.*; import java.util.StringTokenizer; public class EchoStandard { public static void main( String[] args ) throws IOException {

String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r";

BufferedReader inputFile = new BufferedReader( new InputStreamReader( System.in ) );

PrintWriter outputFile = new PrintWriter( new OutputStreamWriter( System.out ) );

String buffer = null; while( true ) { buffer = inputFile.readLine(); if ( buffer == null ) break; buffer = buffer.toLowerCase();

StringTokenizer tokens = new StringTokenizer(buffer,delimiters); while( tokens.hasMoreElements() ) {

String word = tokens.nextToken(); outputFile.println( word );

} // end while

} // end while( true )...

} // end main

} // end class EchoStandard

Echo

BufferedReader inputFile = new BufferedReader( new FileReader( args[0]) );

PrintWriter outputFile = new PrintWriter( new FileWriter( args[1]) );

vs. EchoStandard

BufferedReader inputFile = new BufferedReader( new InputStreamReader( System.in ) );

PrintWriter outputFile = new PrintWriter( new OutputStreamWriter( System.out ) );

Exercise

• Turn Echo.java into EchoV2.java, which behaves just like Echo, except that it takes two optional command-line arguments: the names of the input file and output file, respectively.

• If the user omits the second argument, the program writes to standard output.

• If the user omits both arguments, the program reads from standard output and writes to standard output. For example:

$ java EchoV2 hamlet.txt hamlet.out

$ less hamlet.out

1604 the tragedy of

...

Exercise - More Examples

$ java EchoV2 EchoV2.java

...

$ java EchoV2 hamlet.txt | less (interesting that the pipe “|” is not args[1])

1604 the tragedy of

...

$ java EchoV2

...

$ cat hamlet.txt | java EchoV2 | less

1604 the tragedy of

...

Homework #3 - Interacting with Files

• Extend the MemoPad program so it can save and load memos to and from files

• You’ll need to add two responsibilities to the MemoDatabase interface:

– loading from a file

– saving to a file

homework03-template.zip

• a new MemoPadApp.java that only creates instances

MyMemoDatabase. It accepts a single optional argument, the maximum size of the database.

java MemoPadApp // creates a default student database java MemoPadApp 100 // creates a database with up to 100 memos

• all of the graphics and management classes necessary to compile your application

• a jar file that will let you run a working program, to see how your program should work. Just use this command: java -jar memopad.jar // same as first example above java -jar memopad.jar 100 // same as second example above

HW3: Task 1

• Change MemoPadApp.java to create instances of your MemoDatabase class.

– On Lines 8 and 10, MemoPadApp creates instances of a MemoDatabase for the

MemoPad. Put your class's name in place of my class's name. If you named your class

ArrayBasedMemoDatabase, you don't have to do anything!

HW3: Task 2

• 2. Add empty save() and load() methods to your MemoDatabase class.

– This should ensure that your class now implements the extended MemoDatabase interface.

– Compile and run the program to verify this.

– Of course, the Save and Load buttons won't do anything yet

HW3: Task 3

• Write the save() method for your class.

– This method takes a String argument, the name of the file to write. When the user presses the Save to File button, the MemoPad sends the database a save() message, with the current value of the Key: field as the filename.

– You get to decide the format of the data that your

MemoDatabase object writes to the file. For example, my program writes key/value pairs to a file in this format: eugene>>wallingford philip>>east

HW3: Task 4

• Use your improved class to generate three to five data files.

– Compile the program and run it several times, each time saving a new file of memos. Name your files memos1.dat, memos2.dat, .... This will both enable you to verify that your method works and generate test data for the next task!

– Be sure that each file tests something different about your program. For example, it would be useful to have an empty file and at least one file with a large number of memos in it, to test the "boundary conditions" of the program.

HW3: Task 5

• Write the load() method for your class.

– This method also takes as an argument the name of a file, taken from the current value of the Key: field.

– When the user presses the Load from File button, the MemoPad sends the database a load() message.

– This method should read records of the same format as the data written to file by the save() method.

HW3: Task 6

• Use your new-and-improved class to read each of your data files.

– Compile the program and run it several times.

– Verify that your program can read each of the data files you created in Task 4.

– You should also be able to load multiple data files into the same memo pad. (*)

– Also verify that your program can load and save several times during the same execution.

Download