440 likes | 456 Views
Learn about Java Input/Output streams, character vs. byte streams, access modes, common classes, methods, and examples for efficient data handling in Java applications.
E N D
ITI 1221. Introduction to Computing IILab-11 Dewan Tanvir Ahmed University of Ottawa
Today’s Objective • Introduction to inputs/outputs (I/Os) in Java • Further understanding of exceptions
Java I/Os • Java I/Os seem a bit complex at first. • There are many classes. • But also, objects from two or more classes need to be combined for solving specific tasks. • Java is a modern language that has been developed when the World Wide Web was becoming a reality. • As such, the data can be written/read to/from many sources, including the • console/keyboard, • external devices (such as hard disks) or • the network. • The presence of the Web stimulated the creation of classes for handling various encodings of the information (English and European languages but also Arabic and Asian languages; and also binary data).
Definitions • Definition. • A stream is an ordered sequence of data that has a source or a destination. There are two major kinds of streams: character streams and byte streams. • In Java, characters are encoded with 16 bit Unicodes — • character streams are associated with text-based (human readable) I/Os. • The character streams are called readers and writers. This • Byte streams are associated with data-based (binary) I/Os. • Examples of binary data include image and audio files, jpeg and mp3 files • Information can be read from an external source or written to an external source. • Therefore, for (nearly) every input stream (or reader) there is a corresponding output stream (or writer). • Besides input and output, there is a third access mode that is called direct access, which allows to read/write the data in any given order.
Overview • Several classes are found in the I/O package reflecting the fact that I/O involves two different kinds of streams and three different modes of access. • Stream: • character, byte; • Access: • read, write, direct. • The I/O package contains some 50 classes, 10 interfaces and 15+ Exceptions. • On the top of this, generally objects from 2 or 3 classes need to be combined to carry out a basic task. • Example. • InputStreamReader in = new InputStreamReader( new FileInputStream( "data" ) );
Stream • Two abstract classes that define the methods that are common to all input and output streams • InputStream and • OutputStream
InputStream • int read(): • Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. • int read( byte[ • b ):] Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. • close(): • Closes this input stream and releases any system resources associated with the stream.
InputStream • Since InputStream is an abstract class it is never instantiated. • Here are examples of its subclasses: • AudioInputStream, • ByteArrayInputStream, • FileInputStream, • FilterInputStream, • ObjectInputStream, • PipedInputStream, • SequenceInputStream, • StringBufferInputStream. • One of the main InputStream classes that will be of interest to us is the FileInputStream, which obtains input bytes from a file in a file system.
OutputStream • write( byte[ b • ):] Writes b.length bytes from the specified byte array to this output stream. • flush(): • Flushes this output stream and forces any buffered output bytes to be written out. • close(): • Closes this output stream and releases any system resources associated with this stream.
OutputStream • Since OutputStream is an abstract class, subclasses are used to create objects associated with specific types of I/O: • ByteArrayOutputStream, • FileOutputStream, • FilterOutputStream, • ObjectOutputStream and • PipedOutputStream. • FileOutputStream is commonly used. A file output stream is an output stream for writing data to a File. • Two objects are predefined and readily available for your programs. • System.in - is an input stream associated with the keyboard, and • System.out - is an output stream associated with the console.
Reading in • Reading from a file involves creating a FileInputStream object. • We’ll consider two constructors. • FileInputStream( String name ): • This constructor receives the name of the file as an argument. Example, • InputStream in = new FileInputStream( "data" ); • FileInputStream( File file ): • This constructor receives as an argument a File object, which is an abstract representation of an external file. • File f = new File( "data" ); InputStream in = new FileInputStream( f );
Reading in • Having a File object allows for all sorts of operations, such as, • f.delete(); f.exists(); f.getName(); f.getPath(); f.length(); • To name a few. FileInputStream is a direct subclass of InputStream. • The methods that it provides only allow to read bytes.
InputStreamReader • Because a FileInputStream allows to read bytes only, Java defines an InputStreamReader as bridge from byte to character streams. Its usage is as follows. • InputStreamReader in = new InputStreamReader( new FileInputStream( "data" ) ); or • InputStreamReader in = new InputStreamReader( System.in ); • where System.in is generally associated with the keyboard of the terminal.
int read • int read(): • Reads a single character. • Returns -1 if the end of stream has been reached. • The return type is int, the value -1 indicates the end-of-file (eof) (or end-of-stream (eos)). • The value must be interpreted as a character, i.e. must be converted, • int i = in.read(); if ( i != -1 ) char c = (char) i;
Unicode // The characters in java are represented as Unicodes. public class Unicode { public static void main( String[] args ) { for ( int i=0; i<args.length; i++ ) { String s = args[ i ]; for ( int pos=0; pos < s.length(); pos++ ) { char c = s.charAt( pos ); int u = (int) c; System.out.printlnln( "char = " + c + ", unicode = " + u ); } } } }
Unicode (cont..) // Compile this file // // > javac Unicode.java // // Execute the program passing characters on the command line, // // > java Unicode abcABC 123 ",:/" // char = a, unicode = 97 // char = b, unicode = 98 // char = c, unicode = 99 // char = A, unicode = 65 // char = B, unicode = 66 // char = C, unicode = 67 // char = 1, unicode = 49 // char = 2, unicode = 50 // char = 3, unicode = 51 // char = ,, unicode = 44 // char = :, unicode = 58 // char = /, unicode = 47
int read –Example - Keyboard // Reads keyboad input, displays the characters and corresponding Unicodes, // stops when the end-of-stream is reached. import java.io.InputStreamReader; import java.io.IOException; public class Keyboard { public static void main( String[] args ) throws IOException { InputStreamReader in = new InputStreamReader( System.in ); int i; while ( ( i = in.read() ) != -1 ) { char c = (char) i; System.out.printlnln( "unicode = " + i + ", char = " + c ); } System.out.printlnln( "bye" ); } }
Int read (char [] b) • Read characters into an array. • Returns the number of characters read, or -1 if the end of the stream has been reached. • Examples: InputStreamReader in = new InputStreamReader( new FileInputStream( "data" ) ); • int i = in.read(); if ( i != -1) char c = (char) i; or • char[] buffer = new char[ 256 ]; num = in.read( buffer );
Excercise • Write a class that reads characters for the keyboard using the method read( char[] b ); • The maximum number of characters that can be read at a time is fixed and determined by the size of the buffer. • char[] buffer = new char[ 256 ]; num = in.read( buffer ); String str = new String( buffer );
Exercise – (cont..) • Run some tests, do you notice anything bizarre? • No matter how many characters you’ve entered the resulting String is always 256 characters long, furthermore, it contains several characters that are not printlnable. • You must the method trim to remove those non-printlnable characters InputStreamReader in = new InputStreamReader( System.in ); char[] buffer = new char[ 256 ]; while ( ( in.read( buffer ) ) != -1 ) { String str = new String( buffer ); str = str.trim(); System.out.printlnln( str ); }
BufferedReader • Sometimes, the input should be read one line at a time. • For this, you will be using an object of the class BufferedReader. • FileInputStream f = FileInputStream( "data" ); InputStreamReader is = new InputStreamReader( f ); BufferedReader in = new BufferedReader( is ); or • BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream("data") ) ); • String s = in.readLine();
Copy and Exception Handling import java.io.*; public class Copy { public static void copy(String fileName) throws IOException, FileNotFoundException { InputStreamReader input = null; try { input = new InputStreamReader(new FileInputStream(fileName)); int c; while ((c = input.read()) != -1) { System.out.write(c); } } finally { if (input != null) input.close(); } }
Copy and Exception Handling (cont..) public static void main(String[] args) { if (args.length == 0) { System.out.printlnln("Usage: java Copy file [file|...]"); System.exit(0); } for (int i=0; i<args.length; i++) { String fileName = args[i]; System.out.printlnln(fileName + ":"); try { copy(fileName); } catch (FileNotFoundException e) { System.err.printlnln("File not found ("+fileName+"): "+e.getMessage()); } catch (IOException e) { System.err.printlnln("Cannot read file ("+fileName+"): "+e.getMessage()); } } }
Exercise • Write a class that printlns all the lines that contain a certain word. For each line containing the word, println the line number followed by the line itself.
Find import java.io.*; public class Find { public static void find( String fileName, String word ) throws IOException, FileNotFoundException { BufferedReader input; input = new BufferedReader( new InputStreamReader( new FileInputStream( fileName ) ) ); int lineNumber = 0; String line; while ( ( line = input.readLine() ) != null ) { lineNumber++; if ( line.indexOf( word ) != -1 ) System.out.printlnln( lineNumber + ":" + line ); } input.close(); }
Find - (cont..) public static void main( String[] args ) throws IOException, FileNotFoundException { if ( args.length != 2 ) { System.out.printlnln( "Usage: java Find file word" ); System.exit( 0 ); } find( args[0], args[1] ); }
More Exercises • Write a class that counts the number of occurrences of a given word within a file. • Write a class that fetches the content of a Web page and printlns it on the console.
WGet import java.net.URL; import java.net.MalformedURLException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class WGet { public static void wget( String spec ) throws MalformedURLException, IOException { URL url = new URL( spec ); BufferedReader in = new BufferedReader( new InputStreamReader( url.openStream() ) ); String line = null; while ( ( line = in.readLine() ) != null ) { System.out.printlnln( line ); } in.close(); }
Writing Out • Writing to a file involves creating a FileOutputStream object. • We’ll consider two constructors. • FileOutputStream( String name ): • Creates an output file stream to write to the file with the specified name. • OutputStream out = new FileOutputStream( "data" ); • FileOutputStream( File file ): • This constructor receives as an argument a File object, which is an abstract representation of an external file. • File f = new File( "data" ); • OutputStream out = new FileOuputStream( f ); • FileOutputStream is a direct subclass of OutputStream. The methods that it provides only allow to write bytes.
OutputStreamWriter • Because FileOutputStream allows to write bytes only. Java defines an OutputStreamWriter as a bridge from character streams to byte streams. Its usage is as follows. • OutputStreamWriter out = new OutputStreamWriter( new FileOutputStream( "data " ) ); or • OutputStreamWriter out = new OutputStreamWriter( System.out ); • OutputStreamWriter err = new OutputStreamWriter( System.err ); • System.err is the standard destination for error messages.
OutputStreamWriter (cont..) • write( int c ): • Write a single character. • write( char[ • buffer ):] Write an array of characters. • write( String s ): • Write a String.
OutputStreamWriter (cont..) import java.io.*; public class Copy { public static void copy( String src, String dst ) throws IOException, FileNotFoundException { InputStreamReader input; input = new InputStreamReader( new FileInputStream( src ) ); OutputStreamWriter output; output = new OutputStreamWriter( new FileOutputStream( dst ) ); int c; while ( ( c = input.read() ) != -1 ) { output.write( c ); } input.close(); output.close(); } … }
printlnWriter • printlns formatted representations of objects to a text-output stream. It implements the following methods. • println( boolean b ) println a boolean value. • println( char c ) println a character. • println( char[] s ) println an array of characters. • println( double d ) println a double-precision floating-point number. • println( float f ) println a floating-point number. • println( int i ) println an integer. • println( long l ) println a long integer. • println( Object obj ) println an Object. • println( String s ) println a String.
printlnWriter • Similarly, the following methods also terminate the current line by writing the line separator string. • println( boolean b ) print a boolean value. • println( char c ) print a character. • println( char[] s ) print an array of characters. • println( double d ) print a double-precision floating-point number. • println( float f ) print a floating-point number. • println( int i ) print an integer. • println( long l ) print a long integer. • println( Object obj ) print an Object. • println( String s ) print a String.
Exceptions • IOException • “Signals that an I/O exception of some sort has occurred. • This class is the general class of exceptions produced by failed or interrupted I/O operations.” • This is a direct subclass of Exception, this is therefore a checked exception that must be handled, caught by a catch clause or declared. • FileNotFoundException • The constructor FileInputStream( String name ) throws an exception of type FileNotFoundException, which is a direct subclass of IOException. • This exception must be handled, i.e. caught by a catch clause or declared.
Finally • The finally clause of a try statement is executed whether or not an exception was thrown. • Object val = null; try { val = pre(); // one or more statements } finally { if ( val != null ) post(); } • If pre() succeeds it will return an Object. In the finally clause, we know that pre() has succeeded if val is not null. Here is an application of this idiom for closing a file, even if an error has occurred.
Finally (cont..) • public static void copy( String fileName ) throws IOException, FileNotFoundException { InputStreamReader input = null; try { input = new InputStreamReader( new FileInputStream( fileName ) ); int c; while ( ( c = input.read() ) != -1 ) { System.out.write( c ); } } finally { if ( input != null ) input.close(); } } • Most operating systems impose a limit on the maximum number of files that can be opened simultaneously • Notice that the try statement has no catch clause, therefore both checked exceptions that can be thrown must be declared.
Formatting • java.text.Format • Format is the abstract superclass of all the formatting classes, namely DateFormat and NumberFormat. • See what occurs when printing a floating point number • In order print only a fixed number of decimals, one needs to create a NumberFormat instance and tell this instance how to format numbers. • First, the NumberFormat class is not imported by default, therefore you will have to import it into your program. • Next, you will create and instance and then use the instance methods setMaximumFractionDigits and setMinimumFractionDigits to set the number of digits for the fractional part to 2. • Finally, you can use the instance method format, of the number format object, to create the string representations.
Formatting (cont..) • import java.text.NumberFormat; public class Test { public static void main( String[] args ) { NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); System.out.println( nf.format( 1.0/3.0 ) ); System.out.println( nf.format( 100.0 ) ); } }
DecimalFormat • Alternatively, an Object of the class DecimalFormat, a direct subclass of NumberFormat, can be used. • The following example prints a fractional number with 3 decimals and a width of 8 characters. • import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; float X,Y = .....; String format1 = "###0.000" ; static DecimalFormat fm1 = new DecimalFormat( format1, new DecimalFormatSymbols( Locale.US ) ); System.out.println("X=" + fm1.format(x) + ", Y=" + fm1.format(y));
PlayListManager • For this laboratory, you will modify the program PlayListManager to read and write Songs from and to a file.
Get Songs from File public static PlayList getSongsFromFile( String fileName ) throws IOException, FileNotFoundException { BufferedReader input; input = new BufferedReader( new InputStreamReader( new FileInputStream( fileName ) ) ); PlayList result = new PlayList(); int lineNumber = 0; String line; while ( ( line = input.readLine() ) != null ) { result.addSong( Song.parseSong( line ) ); } input.close(); return result; }
Write Songs to File public void writeSongsToFile( String fileName ) throws IOException, FileNotFoundException { PrintWriter output; output = new PrintWriter(new OutputStreamWriter( new FileOutputStream( fileName ) ) ); for ( int i=0; i<count; i++ ) { output.println( songs[ i ] ); } output.close(); }