Recursion and Streams Recursion: Simply put recursion is a programming method for looping a function until some condition is met by having the function call itself. Most of you are familiar with recursion in C and recursion in java is very similar. A simple example follows. public class SumUpTo { public static int sum(int x) { int sum = 0,i=0; for(i=0;i<=x;i++) { sum = sum + i; } return sum; } public static int recursivesum(int x) { if (x <= 1) return x; else return x + recursivesum(x - 1); } } This class provides two examples of functions which take a number, say 4, and calculate the sum of that number and all numbers leading up to it. In this case 4 + 3 + 2 + 1 = 10. The first function shows how this might be done normally and the second example shows how this function might be programmed using recursion. You can see that in the line "return x + recursivesum(x - 1);" the recursivesum function calls itself. to use this class simply add the lines import SumUpTo to the top of your program and then Sum = SumUpTo.recursivesum(Number); or Sum = SumUpTo.sum(Number); Streams: When its time for you to do input output in java you are going to be using streams to do it. Many of you are already familiar with one basic stream command System.out.println(). However while System.out.println() may closely mimic the abilities and ease of use of printf in C, when we come to scanf and other i/o devices we must dig a little deeper to understand what exactley we need to do to get the desired effect. All i/o in java between the user and the program, the program and files or any number of processes to each other is handled by streams. Simply put java uses streams, input streams, to read data from an input source, such as the keyboard or a file. The basic input stream classes supported by java are: InputStream - serves as the base class for all the other input stream classes. BufferedInputStream - reads data from the buffer to minimize number of actual reads needed. DataInputStream - reads data objects from a stream rather than bytes like most other input streams FileInputStream - Reads data from a file StringBufferInputStream - Reads character data into an array of characters(a string) InputStream: Input stream the superclass of all other string classes defines the following methods. int read(); int read(byte buffer[]); int read(byte buffer[],int offset, int length); long skip(long bytestoskip); int available(); void mark(int readlimit); void reset(); boolean markSupported(); void close(); Taking a more in depth look: int read(); - Takes no parameters and simply reads a byte of data from the input stream and returns it as an integer. Returns a -1 if the end of the input stream is reached. Because it returns a byte of input as an int you'll need to caste it to a char if you're reading characters. (basically stick a (char) in front of this portion of the statement. See the subsequent GetChars class to see this read in action. int read(byte buffer[]); - Takes an array of bytes as its only parameter, enabling you to read multiple bytes of data at once. This version returns the actual number of bytes read or -1 if the end of the stream is reached. See GetChars2. int read(byte buffer[],int offset,int length) - Takes a byte array, an integer offset and and an integer length as parameters. Similar to the second type but this one allows you to specify where in the byte array you want the new information placed. See GetChars3. long skip(long bytestoskip); - used to skip over bytes of data in the input stream. takes a long value as its only input which indicated the number of bytes to be skipped. Returns the actual number of bytes skipped or -1 if the end of the input stream is reached. int available(); - used to determine the number of bytes of input data available to be read. int mark(int readlimit); - marks the current position in the stream. This position can later be returned to using the reset method. The mark and reset methods are useful in situations where you want to read ahead in the stream but not lose your original position. The readlimit is how many bytes can be read ahead and still reset to the marked position. The book I'm using gives an example of someone using the mark/reset to verify a file type. You would basically read the file header(the filename minus the extension) first and then mark the point that the header ends. Then, say we were looking for an image file, we would read the extension and compare it to .bmp. If it wasn't a bmp we could reset and look to see if it was maybe a .jpg etc. boolean marksupported; - marksupported returns a boolean value representing if an input stream supports the mark/reset functionality. void close(); - closes an input stream and releases any resources associated with the stream. It is not necessary to explicitly call close since input stream are automatically closed when the input stream object is destroyed. Though unecessary it is seen as good programming practice to call close after you finish using a stream as it causes the stream buffer to be flushed, which helps avoid file corruption. Now we'll take a look at reading input from the keyboard using these various reads(as they are the string commands most of you will be interested in using). This first example is a simple program that gets input from the keyboard using the first read method turns it into a string and spits it back out again using println. class GetChars { public static void main(String args[]) { StringBuffer s = new StringBuffer(); char c; try { while((c = (char)System.in.read()) != '\n') { s.append(c); } } catch(Exception e) { System.out.println("Error"); } System.out.println(s); } } note that we use string buffer because we have a variable length string. StringBuffer comes in useful when we knows strings will change in value or length. More on that next week.(character and string data). now we'll take a look at the second type of read which does much the same thing as the first upon compilation and execution. class GetChars2 { public static void main(String args[]) { byte buf[] = new byte[80]; try { System.in.read(buf); } catch (Exception e) { System.out.println("Error"); } String s = new String(buf); System.out.println(s); } } We now start off this program by declaring a byte array which the second type of read accepts as its input. Later we convert this to a normal string for printout by using a String constructor which takes a byte array as one of its arguments. now we'll take a look at using the final version of read input (buffered array with offset and length) to get input from the keyboard. Note that in this example I place an 'a' in the first position of our byte array. When it comes time to read in some input, I set the offset within the given byte array to be one thus perserving our original a at the beginning of the string. Thus if you enter "hello" this program will output "ahello." In addition this byte array has only ten character so the lenght must be limited to ten - offset = 9. Anything you type in beyond 9 characters won't be echo'd back out by the program. class GetChars3 { public static void main(String args[]) { byte buf[] = new byte[10]; buf[0] = 'a'; try { System.in.read(buf,1,9); } catch(Exception e) { System.out.println("Error"); } String MyString = new String(buf); System.out.println(MyString); } } Now looking at the BufferedInputStream class which provides a buffered stream of input :). Basically this means that more data is read into the buffered stream than you might have requested, subsequent reads will come straight out of of the buffer rather than the input device. BufferedInputStream has no new methods past those given it by InputStream but it does have 2 new constructors: BufferedInputStream(InputStream in); BufferedInputStream(InputStream in,int size); Both constructors take an input stream as their first object, however in the first buffer a default buffer size is used. In the second you are allowed to specify your buffer size. BufferedInputStream class also defines a handful of member variables which follow: byte buf[]; - array where input data is actually stored int count; - keeps up with how many bytes are stored in the buffer int pos; - keeps up with the current read position of the buffer int markpos; - specifies the current mark position (-1 if it hasn't been set) int marklimit; - max number of bytes that can be read before mark is no longer valid. An example using buffered input follows. import java.io.*; class GetChars4 { public static void main(String args[]) { BufferedInputStream Scooby = new BufferedInputStream(System.in); byte buf[] = new byte[80]; try { Scooby.read(buf,0,80); } catch(Exception e) { System.out.println("Error"); } String MyString = new String(buf); System.out.println(MyString); } } note that unlike InputStream, BufferedInputStream must be imported from java.io package. DataInputStream comes into effect when one needs to read an integer or some other data type from the keyboard or another device. DataInputStream implements many methods to help it in this: String readLine(); boolean readBoolean(); byte readByte(); int readUnsignedByte(); short readShort(); int readUnsignedShort(); char readChar(); int readInt(); long readLong; float readFloat(); double readDouble(); an example of using a DataInputSteam to read input from the keyboard follows.. import java.io.*; class GetInt { public static void main(String args[]) { int Number = 0; DataInputStream in = new DataInputStream(System.in); String s = new String(); try { s = in.readLine(); Number = Integer.valueOf(s).intValue(); System.out.println(Number); } catch(Exception e) { System.out.println("Error"); } } } The FileInputStream class is useful for getting input from a file. It has 3 additional constructors FileInputStream(String name) FileInputStream(File file) FileInputStream(FileDescriptor fdObj) a simple example of reading character data from a file: import java.io.*; class ReadFile { public static void main(String[] args) { byte buffer[] = new byte[50]; try { FileInputStream Scooby = new FileInputStream("test.txt"); Scooby.read(buffer,0,50); } catch(Exception e) { System.out.println("Error"); } String s = new String(buf); System.out.println(s); } } basically this just reads 50 chars from the file "test.txt" much the same way as the preceeding programs read from stdin. Output: Much the same as input streams accept input from devices processes etc. output streams write out to these things. Output Streams are made up by 5 basic classes: OutPutStream - defines the fundamental behavior of the output streams PrintStream - Used for outputting text. BufferedOutPutStream - provides support for buffered output DataOutPutStream - used to output primitive data types (int, float, etc.) FileOutPutStream - outputs data to files. OutputStream serves as the superclass of all other output classes much the same as InputStream did for all input classes. OutPutStreams classes are as follows: void write(int b); void write(byte b[]); void write(byte b[],int offset,int length); void flush(); void close(); The classes are fairly self explanatory, the first write class writes out a single byte, the second an array of bytes and the third an array of bytes with an offset and length which works in a similar fashion to the input functions which take these same arguments. The heart of the output used in most simple programs comes with the use of the PrintStream class. PrintStream gets two new constructors: PrintStream(OutputStream out) and PrintStream(OutPutStream out, boolean autoflush), autoflush adds the handy capability of flushing the stream every time it encounters a new line character. PrintStream also gets a load of methods. Everyones favorite System.out.println() is actually coming from PrintStream. boolean checkError(); void print(Object obj); void print(String s); void print(char s[]); void print(char c); void print(int i); void print(long l); void print(float f); void print(double d); void print(boolean b); void println(); void println(Object obj); void println(String s); void println(char s[]); void println(char c); void println(int i); void println(long l); void println(float f); void println(double d); void println(boolean b); as you can see this lets you output just about whatever you like to the screen or wherever else you might want. Some things that you should note. println() which takes no arguments will simply generate a new line character. The primary difference between say, void print(int i); and void println(int i); is the automatic addition of the newline character at the end of every println. The BufferedOutputStream adds no new functionality(in the way of methods) to the Output. It gets 2 new constructors where it may accept either a OutputStream with the default size or one with a specified size for the buffer. Its just like OutputStream but its buffered basically. DataOutPutStream is used for outputting data in their data formats. It accomplishes this through the use of a few new methods: void writeBoolean(boolean b) void writeByte(byte b) void writeShort(short b) void writeChar(char b) void writeInt(int b) void writeLong(long b) void writeFloat(float b) void writeDouble(double b) void writeBytes(string s) void writeChars(string s) Finally for writing out to Files we come to FileOutputStream. This class has no new methods but it does get 3 new constructors which help it in its specific job of writing to files. They are: FileOutputStream(String name); FileOutPutStream(File file); FileOutPutStream(FileDescriptor Description); The First takes a filename and the second and third take predefined objects. Trying to bring this all out of the abstract and into code you can use a simple output example follows: Bascially what this program does is read input from the keyboard and then output it to a file. import java.io.*; class WriteFile { public static void main(String args[]) { byte buf[] = new byte[64]; try { System.in.read(buff,0,64); } catch(Exception e) { System.out.println("Error"); } try { FileOutPutStream Scooby = new FileOutPutStream("Output.txt"); Scooby.write(buf); } catch(Exception e) { System.out.println("Error"); } } }