Please send questions to st10@humboldt.edu .

CIS 480 - Advanced Java - Random Notes, 4-9-01

--------
finally note:

*   as someone noted last time, if a try-catch block includes
a "finally" clause, then the statements of that clause are
ALWAYS performed;

       *   this was indeed the desire in example FileCopy.java,
       where no matter WHAT happened, exceptions-wise, we
       wanted the open files streams closed;

*   from Barnes, "Object Oriented Programming with Java - An
Introduction", Prentice-Hall, 2000, p. 326, there is a nice
example that lets you "test" if you "get" how the finally
clause works:

        public void method()
        {
		try
		{
			// T2 might throw an exception
			statement_T1;
			statement_T2;
			statement_T3;
		}
		catch (Exception e)
		{
			Statement_C;
		}
		finally
		{
			Statement_F;
		}
	}


	*   now, consider: no exception is thrown. What statements
	are done?

	    T1, T2, T3, F

	*   T2 throws an exception; What statements are done?
	
	    T1, T2, C, F
        
*   so, "finally" is lovely for "housekeeping" tasks that MUST
be done, no matter what.
        *   closing of files is one such classic housekeeping
	task!

	*   but, CARE must be taken to write them so that they
	"work" properly in all cases, whether exceptions have
	occurred or not. 
		 *   thus the care, in FileCopy.java, to check
		 if the File objects are non-null before
		 attempting to close them!

*   one more very-cool nuance: finally is NOT the same as simply
writing statements *after* the try-catch block. Why?
	*   [Barnes, p. 326] "...[the finally clause's] statements
	are executed even if one of the other clauses causes the
	method to terminate --- via a return statement or a propagated
	exception." (!!)

	*   "In the case of a return statement, the return is
	delayed until the finally clause has completed."

END of finally note
--------------------

--------------------
File I/O continued

*   (see Parrot.java for simple example of terminal input...such input
also appears in FileCopy.java;)

*   last time: we got to discuss FileCopy.java a tiny bit, but not the
examples TryWriteToFile.java, TryReadFromFile.java

*   A few more file I/O nuances before proceeding to JDBC:

*   A complication in Java (that we haven't mentioned yet) is
that Java represents characters using something called Unicode ---
the Unicode character set.
        *   not ASCII! (or EBCDIC), two other prominent character
	sets;

*   So, for some of Java's i/o methods provided in the package
java.io:
	*   some input methods will automatically convert data from 
	however the host operating system stores it into Unicode for 
	use within Java,

	*   some output methods will automatically convert Unicode data 
	into the format expected by the host operating system;

	*   (and some Stream classes do NO such conversion, as in
	byte-oriented I/O where you do not want that)

*   in GENERAL:
        *   binary files are processed by subclasses of
		   InputStream
		   OutputStream

		   *   no Unicode conversion is done --- [Barnes, p. 339]
		   "capture the external representation of data"

	*   text files are processed by subclasses of
		   Reader
		   Writer

		   *   Unicode conversion IS done --- [Barnes, p. 339]
		   "designed to convert a wide range of character-based
		   data to and from the internally-used Unicode
		   representation"

*   hopefully, you can see why instances of stream classes
FileInputStream and FileOutputStream thus made more sense
in FileCopy.java than reader/writer subclasses would have;


hmmm... what next?

basic File I/O steps:

*   create your File object
    File   myFile;
    myFile = new File(myFileName);	// myFileName is a String

        *   NOT the only File constructor, remember; another takes
	two arguments, a directory File instance and a file File
	instance (as seen in FileCopy.java), etc.

*   (you can check on a File's status in many wonderful and interesting
ways, only a few of which were demo'd in Delete.java and FileCopy.java;
see the Java API, package java.io, package File)
        *   (you can also make directories, make a file readable,
	etc.)

	*   it looks accepted to throw an IOException if an input
	file name is not suitable --- makes sense, that info is
	thus unsuitable input...!

*   now, you need to pick which of those lovely 40 or so stream
classes in java.io you wish to use to perform input or output;

*   For reading and writing of text files, FileReader and FileWriter
are convenient and often used (although they are often also
wrapped in BufferedReader instances and BufferedWriter instances,
as we shall see).
        *   note that there are constructors that create FileReader
	and FileWriter instances both using a file's String name
	as a parameter, and using a File instance as a parameter;

	*   one of FileWriter's constructors also lets you have
	TWO arguments, a filename given as a String and a boolean;
	if the boolean is set to true, then the file is opened
	for APPENDING (its current contents are not nuked, as
	they are otherwise).

	*   (yes, otherwise the creation of a FileWriter stream
	for a file DOES cause the current contents to be destroyed;)

*   you can use BufferedReader and BufferedWriter classes (subclasses
of Reader, Writer) if you want to read or write a whole LINE at
a time;
        *   and, when you do, you get to deal with that line as
	a String, if you'd like, instead of as an array of
	characters --- convenient!

	*   however, perhaps oddly, (Barnes, p. 347) "the buffered
	classes simply act as wrappers around the objects they were
	constructed with, which they retain as an attribute" ---

	*   so, one creates a BufferedReader or BufferedWriter 
	instance by constructing from an existing Reader
	Writer object (or appropriate subclass of Reader or
	Writer).

	*   you never even use the name of the Reader or Writer
	used for this purpose --- closing the BufferedReader or
	BufferedWriter closes both --- so it is very common for
	it to be declared anonymously. 

	*   and so, in FileCopy.java, you have:

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

	       *   ...around an instance of InputStreamReader, which
	       is fine because InputStreamReader is a Reader subclass;

	       *   (InputStreamReader is fine here for reading in from 
	       System.in; putting the BufferedReader around it then lets
	       you read from System input one line at a time...)

        *  and in new-revised-and-improved TryReadFromFile.java,
	you have:

BufferedReader	fromStream;
...
fromStream = new BufferedReader(new FileReader(fileToRead));

	       *   ...around an instance of FileReader, which
	       is the appropriate class for reading text from
	       a File instance;

	       *   but, by wrapping the FileReader instance in
	       a BufferedReader instance, you can read the file
	       in one whole line at a time;

	*  now, this is not done in any of the examples, but you
	can also have something like:

BufferedWriter    myBWriter;
...
myBWriter = new BufferedWriter(new FileWriter(outputFilename));

		*   ...and now you can write a String line
		at a time into the file.
		
	*   notice, then --- instantiating the stream here
	IS opening the file;
	        *   and, it CAN throw a FileNotFoundException
		(if the file cannot be found OR if it cannot be
		opened for ANY reason...) 

		*   I've added a catch block checking for
		this to revised/improved versions of
		TryWriteToFile2, TryReadFromFile

	*   when done, it is ESPECIALLY important to close the
	stream --- 
	        in.close()		(in FileCopy.java)
	        fromStream.close()	(in TryReadFromFile.java)
	        myBWriter.close()	(somewhere after the above ex.)

		*   do NOT assume the end of a program automatically
		closes files and flushes buffers --- NOT SO!

	        *   a close() CAN throw an IOException?! (although it
		is unlikely) --- but you might want a catch to
		deal with it, thus;

		*   fortunately, since problems with reads and writes
		can also throw this exception, your try-catch block
		for this CAN catch it for the close(), too;
		        *   that is what is done in TryReadFromFile,
			TryWriteToFile2.

	*   you CAN make a specific request to force out stuff in the
	internal buffer being held until there's "enough" with
	method flush()

	*   typical ways of reading/writing using these streams,
	once they are set up:
        *    BufferedReader:

	     *   readLine() examples:
	         // from FileCopy
	         String response = in.readLine(); 

	         // latestLine is a String variable; from TryReadFromFile
	         latestLine = fromStream.readLine();

	     *   skip(long n)
		 ...can be used to skip a certain number of characters

	     *   read()   // with NO arguments
		 ...can be used to read a single character, but it returns
		 the character read as an INTEGER, int!

		 (the complementary write() assumes that its int
		 argument is a Unicode character cast as an int,
		 and casts it back to a char before writing it
		 out...!)

	     *   read(char[] cbuf, int offset, int length)
	         ...can be used to read up to length characters
		 into cbuf, starting a cbuf[offset].

		 *   returns the int number of characters read, unless
		 the first attempt to read fails --- in that case,
		 it returns -1

        *   BufferedWriter:

	     *   write(String line)   
	         // if myLine is a String variable...
	         // interesting, the method is NOT writeLine!
	         myBWriter.write(myLine);

	     *   write(int c)
	         ...writes an integer that it assumes is
		 a Unicode character cast as an int (as mentioned
		 above)

	     *   write(String s, int offset, int length)
	     *   write(char[] buf, int offset, int length)
	         ...write a portion of a String or an array of 
		 characters	

             *   newLine()
	         ...writes a line terminator;
	     
*   now that we have talked about the BufferedReader and BufferedWriter,
it isn't that hard to talk about a few of the i/o methods for some
of the other kinds of streams;
        *   for FileReader: (when you haven't wrapped a BufferedReader
	around it...)
	        *   it inherits two read()'s from InputStreamReader
		that are very similar to two of BufferedReader's read()'s:
                
		*   read()
		...can be used to read a single character, but it returns
		the character read as an INTEGER, int!

		    (the complementary write() assumes that its int
		    argument is a Unicode character cast as an int,
		    and casts it back to a char before writing it
		    out...!)
                
		*   read(char[] cbuf, int offset, int length)
	        ...can be used to read up to length characters
		into cbuf, starting a cbuf[offset].

		    *   returns the int number of characters read, unless
		    the first attempt to read fails --- in that case,
		    it returns -1

        *   for FileWriter:
	        *   it inherits three write()'s from OutputStreamWriter,
		which, again, are similar to three of BufferedWriter's
		write()'s; it also inherits two from Writer superclass.
		
		*   from OutputStreamWriter, similar to those in 
		BufferedWriter:
		    *   write(int c)
		    ...writes an integer that it assumes is
		    a Unicode character cast as an int (as mentioned
		    above)

		    *   write(String s, int offset, int length)
		    *   write(char[] buf, int offset, int length)
		    ...write a portion of a String or an array of 
		    characters	
			
		*  from Writer:
		    *   write(char[] buf)
		    ...writes an array of characters; behaves, in effect,
		    like a call write(buf, 0, buf.length)

		    *   write(String str)
		    ...ah! will simply write a String;
		    
		        *   and that's what we are doing in 
			TryWriteToFile2.java, putting the String
			of text from the textarea...

*   now, for the byte-oriented subclasses of InputStream and OutputStream:
        *   read and write bytes, as we've already mentioned;

	*   (so, they'll work for binary format files, note;)

	*   and please note: we're focusing on file-oriented material
	in here today. Many of those 40 stream classes we mentioned
	are not file-oriented at all --- they may [Barnes, p. 351]
	"exist to deliver a stream of bytes to and from other sources
	and sinks, such as an internal array of bytes".

	*   but, FileInputStream and FileOutputStream are indeed
	oriented to deliver such bytes from and to files;

	*   FileInputStream: includes three read()'s
	        *   read():
		[Java 2 API] "reads a byte of data from this input
		stream" expressed as an int

		*   read(byte[] b)
		[Java 2 API] "Reads up to b.length bytes of data 
		from this input stream into an array of bytes."
		"Returns: the total number of bytes read into the
		buffer, or -1 if if there is no more data because 
		the end of the file has been reached."		
	
		*   read(byte[] b, int offset, int length) 
                [Java 2 API] "Reads up to length bytes of data from this 
		input stream into an array of bytes" (starting at
		offset)? Also returns the total number of bytes
		read or -1 if there is no more data because the
		end of the file has been reached.

		*   note that read(byte[] b) is the version used in
		FileCopy.java;
		
	*   FileOutputStream: includes three write()'s
	        *   write(int b)
		[Java 2 API] "Writes the specified byte to this file 
		output stream" (presumably a byte in the form of an
		int...)

		*   write(byte[] b)
		[Java 2 API] "Writes b.length bytes from the specified 
		byte array to this file output stream."

		*   write(byte[] b, int offset, int length) 
                [Java 2 API] "Writes length bytes from the specified 
		byte array starting at offset offset to this file output 
		stream."

		*   note that write(byte[] b, int offset, int length)
		is the version used in FileCopy.java; HAS to be,
		because cannot be sure actually READ buffer.length
		bytes in the read() preceding this write();

*   now, as you have probably guessed, there is a LOT more about file
input and output, and even more about input and output streams in
general, in java.io. 
        *   as a small for-example: filter streams, streams to and
	from pipes, stream tokenizers, etc.!

*   But, this mostly-file-oriented start can take you far,
and help you be able to investigate more on your own from here...