COMPSCI 230 S2 2016 Software Construction File Input/Output 2 Agenda & Reading Agenda: Introduction Byte Streams FileInputStream & FileOutputStream BufferedInputStream & BufferedOutputStream Character Streams FileReader & FileWriter BufferedReader & BufferedWriter Scanning System.in : The Standard Input Streams Reading: The Java Tutorial: http://java.sun.com/docs/books/tutorial/essential/io/index.html Byte Streams handle I/O of raw binary data. Character Streams handle I/O of character data, automatically handling translation to and from the local character set. Buffered Streams optimize input and output by reducing the number of calls to the native API. Scanning 3 Python Vs Java Python: The input function displays its argument as a prompt and waits for input When the user presses the Enter or Return key, the function returns a string representing the input text. name = input("enter your name: ") Java: age = int(input("enter your age: ")) The Scanner class is used for the input of text and numeric data from the keyboard. The programmer instantiates a Scanner and uses the appropriate methods for each type of data being input. Scanner in = new Scanner(System.in); fahr = in.nextdouble(); Return type Method Name Description boolean hasnext() returns true if more data is present boolean hasnextint() returns true if the next thing to read is an integer String next() returns the next thing to read as a String int nextint() returns the next thing to read as an integer 5.1 Introduction Input/Output Overview This topic covers the Java platform classes used for basic I/O with text and binary files. Data is input from and output to programs Input from keyboard or a file Output to display (screen) or a file Advantages of File I/O Permanent copy Output from one program can be input to another Input can be automated (rather than entered manually) Often a program needs to bring in information from an external source or to send out information to an external destination. The information can be anywhere: in a file, on disk, somewhere on the network, in memory, or in another program. Also, the information can be of any type: objects, characters, images, or sounds. 4
5.1 Introduction Streams Stream: An object that either delivers data to its destination (screen, file, etc.) or that takes data from a source (keyboard, file, etc.) It acts as a buffer between the data source and destination Input stream A stream that provides input to a program Example: System.in 5.1 Introduction Text Files and Binary Files Text Files designed to be read by human beings, and that can be read or written with an editor can also be called ASCII files Platform independent Human readable Output stream A stream that accepts output from a program Example: System.out Algorithms for sequentially reading and writing data are basically the same: Binary Files View in Binary format End-of-line symbol designed to be read by programs and that consist of a sequence of binary digits more efficient to process than text files represent other types encoded information, such as executable files, images or sounds 5 Reading: Open a stream While more information Read information Close the stream Writing: Open a stream While more information Write information Close the stream 6 Binary format 5.1 Introduction java.io Package All Java I/O classes are defined in the java.io package To use these classes, a program needs to import the java.io package import java.io.*; Most of the java.io classes implement sequential access streams. The stream classes are divided into two types: Byte Streams Streams that are used to read raw data Character Streams Streams that are used to read text data Byte Streams Streams that are used to read and write binary data such as images and sounds Methods of InputStream int read(): reads the next byte of data from the input stream void close(): closes this input stream Methods of OutputStream void close(): closes this output stream void write(int b): writes the specified byte to this output stream void flush(): flushes this output stream and forces any buffered output bytes to be written out 7 Byte stream provide a convenient means for handling input and output of bytes. Therefore, byte stream are used for reading or writing binary data. Character streams provide a convenient means for handling input and output of characters. 8
File Streams File streams that are used to read or write from a file on the native file system FileInputStream FileOutputStream Sequence of steps for binary input: open a file while there is more information to read read the information close the file Sequence of steps for binary output: open a file while there is more information to write write the information close the file FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader. 9 Exception Handling When performing file I/O there are many situations in which an exception may be thrown FileNotFoundException Many of these exception classes are subclasses of the class IOException The class IOException is the root class for a variety of exception classes having to do with input and/or output These exception classes are all checked exceptions. (require you to handle the exception in some way) You can either handle the exception with a catch-block, or defer it with a throws-clause. // open a file // Read/write information catch (IOException e) { System.out.println("ERROR"); finally { //close the file 10 public static... throws IOException { //Open a file //Read/write information //Close the file Note: Since opening a file can result in an exception, it should be placed inside a try block If the variable for a PrintWriter object needs to be used outside that block, then the variable must be declared outside the block Otherwise it would be local to the block, and could not be used elsewhere If it were declared in the block and referenced elsewhere, the compiler will generate a message indicating that it is an undefined identifier FileInputStream fin = null; // open a file // Read/write information FileInputStream Constructor: FileInputStream fin = new FileInputStream(InfileName); Creates a FileInputStream by opening a connection to an actual file, the file named by the path name InFileName in the file system Throws FileNotFoundException on Error Methods int read() Reads a byte at a time from the file Returns 1 if it reaches the end of the file void close() Closes this file input stream and releases any system resources associated with the stream System.out.println(fin.read()); fin. close(); 11 catch (IOException e) { System.out.println("ERROR"); finally { //close the fin (input stream) If the named file does not exist, is a directory rather than a regular file, or for some other reason cannot be opened for reading then a FileNotFoundException is thrown. If InFileName does not contain a path, the file referred to must be in the same directory as your program file. 12
FileOutputStream Constructor: FileOutputStream fout = new FileOutputStream(OutfileName); Creates an output file stream to write to the file with the specified name Throws FileNotFoundException on Error Methods: void write(int b) Writes the specified byte to the file 97 void close() fout.write(97); fout.close(); a System.out.print(97); Example 1 The following program uses FileInputStream and FileOutputStream to copy the contents of a file named original.bmp into a file called copy.bmp. 1 public static void main(string[] args) throws Exception FileInputStream fin = new FileInputStream(args[0]); FileOutputStream fout = new FileOutputStream(args[1]); int c; while ((c = fin.read())!= -1) 3 fout.write(c); fin.close(); 4 fout.close(); Example: FileByteStreamCopy.java >java FileByteStreamCopy original.bmp copy.bmp 2 If the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason then a FileNotFoundException is thrown. If the file does exist, the previous contents of the file are overwritten. If a program ends normally it will close any files that are open. However, it is good to close all files explicitly. The reason is we would like to make sure all file are closed if a program ends abnormally to prevent corruption of your files. Also, a file open for writing must be closed before it can be opened for reading. 13 IOException is thrown to the default handler provided by the Java run-time system by using a throwsclause. without this, the program does not compile. The IOException will arise if the disk cannot be accessed and the program will terminate. Command line input arguments are passed in the String array args[ ]. So args[0] is the first command line input, args[1] is the second one. It reads bytes from the input stream as long as there's more input in the input file and writes those bytes to the output stream. When the input runs out, the program closes both the input and the output streams. 14 Buffering Speed up input and output by storing data ahead of time read as much data as possible (before you request, storing data ahead) store data in a region of memory called a buffer write entire buffer output to disk at once One long disk access takes less time than many smaller ones BufferedInputStream buffers file input BufferedOutputStream buffers file output Constructors: FileInputStream theinput = new FileInputStream( args[0] ); FileOutputStream theoutput = new FileOutputStream( args[1] ); BufferedInputStream bufinput = new BufferedInputStream( theinput ); BufferedOutputStream bufoutput = new BufferedOutputStream( theoutput); 15 Example 2 The following program uses BufferedInputStream & BufferedOutputStream to copy the contents of a file named original.bmp into another file called copy2.bmp And it uses try, Catch and finally block to handle exceptions that may be generated within the program Example: BufferedByteStreamCopy.java >java BufferedByteStreamCopy original.bmp copy2.bmp BufferedInputStream bin = null; 2 BufferedOutputStream bout = null;... bin = new BufferedInputStream(fin); bout = new BufferedOutputStream(fout);... catch (Exception e) { System.out.println("ERROR"); finally { if (bin!= null) 1 bin.close(); 3 catch (IOException e){ System.out.println("ERROR closing "); if (bout!= null)... 1. The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it s the perfect place to perform cleanup. 2. BufferedInputStream and BufferedOutputStream objects are declared outside the try block. They can be closed in the finally block. 3. The finally clause in turn contain a try & catch block. This is because the close method called in a finally clause can throw an exception. 4. The performance of the above program is better than the pervious example when we copy a large file. 16
Example: BufferedByteStreamCopy2.java Another Example Using throws Exercise 1 public static... throws IOException { BufferedInputStream bin = null; BufferedOutputStream bout = null; FileInputStream fin = new FileInputStream(args[0]); bin = new BufferedInputStream(fin); FileOutputStream fout = new FileOutputStream(args[1]); bout = new BufferedOutputStream(fout); int c; while ((c = bin.read())!= -1) bout.write(c); catch (ArrayIndexOutOfBoundsException e) { System.out.println("Not enough parameter."); catch (FileNotFoundException e) { System.out.println("Could not open the file:" + args[0]); catch (Exception e) { System.out.println("ERROR copying file"); finally { if (bin!= null) bin.close(); if (bout!= null) bout.close(); 17 Complete the following method to read byte values in a binary file. If the byte value is in between 0 to 255, prints the value in decimal. 18 BufferedInputStream bin = null; FileInputStream fin = new FileInputStream(args[0]); bin = new BufferedInputStream(fin); int c; finally { if (bin!= null) bin.close(); Character Streams Streams that are used to read/write characters. Inside a Java program all character data is represented with the 16-bit char data type. However, an ASCII text file contains ASCII characters (8-bit) Character Streams translate between the internal format used by Java programs and an external format used for text files. Most programs should use readers and writers to read and write textual information. FileReader & FileWriter FileReader FileReader fr = new FileReader("in.txt"); Convenience class for reading character files Constructor (throws FileNotFoundException on error) Creates a new FileReader, given the name of the file to read from. Methods: (throw IOException on error) int read(); //read a single character void close(); FileWriter fw = new FileWriter("out.txt"); FileWriter Convenience class for writing character files Constructor (throw IOException on error) Constructs a FileWriter object given a file name. FileWriter(String filename, boolean append) a boolean indicating whether or not to append the data written. Methods: (throw IOException on error) void close() void write(int c); //write a single character void write(string s); //write a String FileNotFoundException - if the named file does not exist, is a directory rather than a regular file, or for some other reason cannot be opened for reading IOException - if the named file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason 19 20
Example 4 Input.txt An I/O Stream represents an input source... Exercise 2 Note: read() : Reads a single character The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached Example: FileReaderEg.java Complete the following method which counts the number of t in the input file. FileReader fr = new FileReader(args[0]); br = new BufferedReader(fr); int c; System.out.println(fr.read()); Prints 65 >java FileReaderEg input.txt FileReader fr = null; int num = 0, count = 0; String message = ""; fr = new FileReader( args[0] ); FileReader fr = new FileReader(args[0]); br = new BufferedReader(fr); int c; System.out.println((char)fr.read()); Should cast it to char before printing finally { fr.close(); System.out.println( count ); 21 22 BufferedReader Read text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines Constructor FileReader fr = new FileReader( args[0] ); BufferedReader br = new BufferedReader( fr ); Method readline() (throw IOException on error) Reads a line of text. Returns null if the end of the stream has been reached String Line = br.readline(); Without buffering, each invocation of read() or readline() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient. The readline() method returns a string. The String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached BufferedWriter Write text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings. Constructor Method newline() (throws IOException on Error) Write a line separator close(), write(int c), write(string s), write(line, offset, len) can be used in BufferedWriter. write(line, offset, len); Write a portion of a String. Offset from which to start reading characters FileWriter fw = new FileWriter( args[1] ); BufferedWriter bw = new BufferedWriter(fw); len - Number of characters to be written bw.write(line, 0, line.length); bw.newline(); 23 24
Example 5 The following program uses BufferedReader & BufferedWriter to copy data line by line FileReader fr = new FileReader(args[0]); FileWriter fw = new FileWriter(args[1]); BufferedReader br = new BufferedReader(fr); BufferedWriter bw = new BufferedWriter(fw); String line;... while ((line = br.readline())!= null) { bw.write(line, 0, line.length()); bw.newline();... br.close(); bw.close(); Example: BufferedCopy.java The program reads from the BufferedReader, which in turn reads from source. The program does this so that it can use BufferedReader's convenient readline method. The readline method reads data from source sequentially. It reads the entire line (to a CR/LF) to the program. When readline tries to read beyond the end of a text file it returns Null, so you can test for null to stop processing a text file. The only way to re-read the file is to close and re-open the file with the BufferedReader. The write method writes the entire string read by the readline method but not including the linetermination characters. The newline method is used to write the line separator after the write method. 25 Exercise 3 Complete the following method which reads a file and reverses each line in the input file. Example: 26 What is the output ->?tuptuo eht si tahw BufferedReader br = null; BufferedWriter bw = null; FileReader fr = new FileReader(args[0]); FileWriter fw = new FileWriter(args[1]); String line, reversestring; while ((line = br.readline())!= null) { reversestring = new StringBuffer(line).reverse().toString(); finally {... PrintWriter It is similar to the FileWriter class in that it can be used to write text files It can print formatted representations of objects to a text-output stream and used to format output in exactly the same way as when it is called by System.out. Constructor PrintWriter pw = new PrintWriter(new FileWriter("out.txt"); Methods: print(string s) Print a string. println(string s) Print a String and then terminate the line. pw.println("hello World"); PrintWriter pw = new PrintWriter(new FileWriter(args[1])); String line; while ((line = br.readline())!= null) { pw.println(line); Example: PrintWriterCopy.java The FileWriter is wrapped in a PrintWriter so that the program can use PrintWriter's convenient println method instead of using the write and newline methods from the previous example. You will often see streams wrapped in this way so as to combine the various features of the many streams. 27 tostring() & println() If a class has a suitable tostring() method, and anobject is an object of that class, then anobject can be used as an argument to System.out.println, and it will produce sensible output The same thing applies to the methods print and println of the class PrintWriter 28 System.out.println(aString); System.out.println(anObject); The tostring() method of the anobject is invoked automatically. pw.println(astring); pw.println(anobject); The tostring() method of the anobject is invoked automatically.
The printf method Example: PrintFExample.java A convenience method to write a formatted string to this writer using the specified format string and arguments. PrintWriter printf(string format,object... args) format - A format string args - Arguments referenced by the format specifiers in the format string. Conversion character b s c D e Data Type boolean String character Decimal integer decimal number in computerized scientific notation decimal number If there are more arguments than format specifiers, the extra arguments are ignored. The number of arguments is variable and may be zero. pw.printf("%s, %d + %d = %d, Apple, 1, 2, 3); Pw.printf ("pi = %5.3f", Math.PI); The format string includes the specifier "%5.3f" that is applied to the argument. The '%' sign signals a specifier. The width value 5 requires at least five characters for the number, the precision value 3 requires three places in the fraction, and the conversion symbol 'f' indicates a decimal representation of a floatingpoint number. 29 f Byte Vs Character streams Which one should I use? Binary format (image file, sound file) use Byte stream Viewed or created by Text Editor use character stream Byte Streams InputStream OutputStream BufferedInputStream BufferedOutputStream FileInputStream FileOutputStream 30 Character Streams Reader Writer BufferedReader BufferedWriter FileReader FileWriter 5.4 Scanning Scanner The scanner breaks input into individual tokens associated with bits of data By default, a scanner uses white space to separate tokens blanks, tabs, and line terminators To use the scanner, a program needs to import the java.util package Supports tokens for all of the Java language's primitive types (except for char) Constructor: Constructs a new Scanner that produces values scanned from the specified input stream. s = new Scanner(new BufferedReader(new FileReader("input.txt"))); 5.4 Scanning Methods Methods: boolean hasnext() Returns true if this scanner has another token in its input. boolean hasnextint() boolean hasnextdouble() String next() Finds and returns the next complete token from this scanner. int nextint() Scans the next token of the input as an int. Scanner usedelimiter(pattern pattern) s.usedelimiter(","); Sets this scanner's delimiting pattern to the specified pattern. 31 32
5.4 Scanning Example 8 A program that reads the individual words in input.txt and prints them out, one per line. Scanner s = null; s = new Scanner(new BufferedReader(new FileReader(args[0]))); while (s.hasnext()) { System.out.println(s.next()); finally { if (s!= null) { s.close(); Example: ScannerEg.java 5.4 Scanning Exercise 4 Returns 27 1 5 7 2 6 1 5 Complete the following program to read reads a list of int values and adds them up Scanner s = null; s = new Scanner(new BufferedReader(new FileReader("numbers.txt"))); int sum = 0; while (s.hasnext( )) { += s. System.out.println(sum); finally { if (s!= null) { s.close(); 33 34 5.4 Scanning hasnext() Vs hasnextint() However, you will get an Exception if the next token of the input is not an int. java.util.inputmismatchexception You can use hasnextint() instead of hasnext() to check for the data type of the next token. while (s.hasnextint( )) { sum += s.nextint(); Returns 21 1 5 7 2 6 f 5 But the program returns 21 (instead of 26) Reading ends when either the end of the file is reach or a token that is not an int is reached. So, the 5 is never read. Use hasnext() & hasnextint() together while (s.hasnext()) { if ( s.hasnextint()) { sum += s.nextint(); else { s.next(); 1 5 7 2 6 f 5 5.5 System.in The Standard I/O Streams The System class provides a stream for reading text - the standard input stream. System.in is a byte stream It is used to read input from the keyboard. System.in The System class provides two streams for writing text - the standard output and the standard error stream (not shown in these notes). System.out System.err These objects are defined automatically and do not need to be opened 35 36
5.5 System.in Reading from System.in Using the BufferedReader class Use readline()to read the entire line Read from System.in (byte stream) Wrap an InputStreamReader within a BufferedReader InputStreamReader It is a bridge from byte streams to character streams It transforms a given raw byte stream into a sequence of characters. Example: ReadFromConsole.java BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Enter a name"); String line = in.readline(); System.in in Java refers to the keyboard in much the same way as System.out refers to the display. System.in will "receive" what is typed on the keyboard. When the "Enter" key is pressed, the entire line typed will become an object consisting of a sequence of bytes (a "byte stream). To convert this to a stream of characters, the byte stream object is passed to the constructor of an InputStreamReader object. This object is passed in turn to the constructor of a BufferedReader object. The BufferedReader class includes a method readline that returns the entire typed line as a single String object. 37 5.5 System.in Reading from System.in Using the Scanner class from System.in Reading the entire line - use nextline() 38 Scanner in = new Scanner(System.in); System.out.print("Enter a name"); String line = in.nextline(); Reading a sequence of words/primitive types from keyboard Note: The Scanner class does not provide any easy way to detect the end of an input line from System.in, so we will use a negative value to indicate the end of the list of integers. int i = in.nextint(); while (i >= 0) { //negative value to stop i = in.nextint(); Example: ScanFromConsole.java