Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
File I/O (Input and Output) Why use files? Things stored in files are more permanent than things stored in variables in programs. Say we have a file called “poem.dat” on disk in some folder. Mares eat oats And does eat oats And little lambs eat ivy. File input Recall how we performed input: Scanner in = new Scanner( System.in ); What is the source of the input? File input Instead of this: Scanner in = new Scanner( System.in ); We’ll use: Scanner in = new Scanner( new FileInputStream("data.txt") ); File input import java.io.FileInputStream; import java.util.Scanner; class MyIO { public static void main ( String args[] ) throws Exception { Scanner in = new Scanner( new FileInputStream("out.txt") ); //… in.close(); } } File input import java.io.FileInputStream; import java.util.Scanner; class MyIO { public static void main ( String args[] ) throws Exception { Scanner in = new Scanner( new FileInputStream("out.txt") ); //… in.close(); } } We’ll use this simpler technique rather than the more powerful and complicated technique used in the text (the try-catch block). Revisiting the Scanner class String next ( ) boolean nextBoolean ( ) Scans the next token of the input as a float. int nextInt ( ) Scans the next token of the input as a double. float nextFloat ( ) Scans the next token of the input into a boolean value and returns that value. double nextDouble ( ) Finds and returns the next complete token (i.e., typically “words” separated by whitespace) from this scanner. Scans the next token of the input as an int. String nextLine ( ) Advances this scanner past the current line and returns the input that was skipped. Additional Scanner class methods String next ( ) Finds and returns the next complete token (i.e., typically “words” separated by whitespace) from this scanner. boolean hasNext ( ) Returns true if this scanner has another token in its input. boolean nextBoolean ( ) Scans the next token of the input into a boolean value and returns that value. boolean hasNextBoolean ( ) Returns true if the next token in this scanner's input can be interpreted as a boolean value using a case insensitive pattern created from the string "true|false". double nextDouble ( ) Scans the next token of the input as a double. boolean hasNextDouble ( ) Returns true if the next token in this scanner's input can be interpreted as a double value using the nextDouble() method. Additional Scanner class methods float nextFloat ( ) Scans the next token of the input as a float. int nextInt ( ) Scans the next token of the input as an int. String nextLine ( ) Advances this scanner past the current line and returns the input that was skipped. boolean hasNextFloat ( ) Returns true if the next token in this scanner's input can be interpreted as a float value using the nextFloat() method. boolean hasNextInt ( ) Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. boolean hasNextLine ( ) Returns true if there is another line in the input of this scanner. SHOW THE CONTENTS OF A FILE (IN A WINDOW) Ex. Output contents of file to screen/window. //open the input file Scanner in = new Scanner( new FileInputStream("poem.dat") ); //read one line from the input file if (in.hasNextLine()) { String s = in.nextLine(); System.out.println( s ); } //read another line from the input file if (in.hasNextLine()) { String s = in.nextLine(); System.out.println( s ); } … in.close(); Ex. Output contents of file to screen/window. //open the input file Scanner in = new Scanner( new FileInputStream("poem.dat") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); System.out.println( s ); } in.close(); Ex. Output contents of file to screen/window. //open the input file Scanner in = new Scanner( new FileInputStream("poem.dat") ); //read & write one line at a time for ( ; ; ) { //what will happen now? String s = in.nextLine(); System.out.println( s ); } //in.close(); //must do this //otherwise, compiler will error w/ //unreachable statement Ex. Output contents of file to screen/window. //open the input file Scanner in = new Scanner( new FileInputStream("poem.dat") ); //read & write one line at a time for ( ; ; ) { //what will happen now? String s = in.nextLine(); System.out.println( s ); } //in.close(); //must do this Mares eat oats //otherwise, compiler will error w/ And does eat oats //unreachable statement And little lambs eat ivy. Exception in thread "main" java.util.NoSuchElementException: No line found at java.util.Scanner.nextLine(Scanner.java:1471) at FileIO.main(MyIO.java:13) Ex. Output contents of file to screen/window. //open the input file Scanner in = new Scanner( new FileInputStream("poem.dat") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); So when reading from a file, System.out.println( s ); we always need some end-of} file (EOF) test. in.close(); Ex. Output contents of file to screen/window. //open the input file Scanner in = new Scanner( System.in ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); When reading from the System.out.println( s ); keyboard under Windows, we } can indicate EOF by pressing ctrl-D followed by Enter. (We in.close(); can also press ctrl-C but that aborts the program immediately.) WRITING TO FILES File output If we look at the definition of Java’s System class, we see that System.out is of type PrintStream. To write to a file, we will use FileOutputStream and PrintWriter. File output To write to a file, we will use FileOutputStream and PrintWriter. import java.io.FileOutputStream; import java.io.PrintWriter; class MyIO { public static void main ( String args[] ) throws Exception { System.out.println( "begin writing to a file" ); PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); out.println( "hello fred." ); out.println( "and ethel." ); //close is required for files. if we forget, the file will be created // but it will be empty! out.close(); System.out.println( "done writing to a file" ); } } Writing to a file (file output) //create a new, empty output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //write something to the output file out.println( "hello fred." ); out.println( "and ethel." ); //close is required for files. // if we forget, the file will be created but it will be empty! out.close(); Writing to a file (file output) //create a new, empty output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //write something to the output file out.println( "hello fred." ); out.println( "and ethel." ); If the file already exists, it will be erased and a new, empty output file will be created. The old contents, if any, will be lost. //close is required for files. // if we forget, the file will be created but it will be empty! out.close(); Writing to a file (file output) //create a new, empty output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt“, true) ); //write something to the output file out.println( "hello fred." ); out.println( "and ethel." ); This will cause new information to be added at the end. The original contents will not be lost. //close is required for files. This is called append mode. // if we forget, the file will be created but it will be empty! out.close(); The other, default mode is called overwrite. Writing to a file (file output) //create a new, empty output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //write something to the output file out.println( "hello fred." ); out.println( "and ethel." ); //close is required for files. // if we forget, the file will be created but it will be empty! out.close(); Close is required because this is buffered I/O: “Rather than physically writing every instance of output data as soon as possible, the data is saved in a temporary location, known as a buffer; when enough data is accumulated in this temporary location, it is physically written to the file. This can add to efficiency, since physical writes to a file can be slow.” MAKING A COPY OF A FILE So how do I write a program to copy one file to another file? Copy one file to another //declare vars & open input and output files Scanner in = new Scanner( new FileInputStream("poem.dat") ); PrintWriter out = new PrintWriter( new FileOutputStream("poem-copy.dat") ); Input file //loop and copy all lines Output file while (in.hasNextLine()) { String s = in.nextLine(); //read a line from input out.println( s ); //write a line to output } out.close(); in.close(); CREATING A SECRET CODE Creating a secret code Problem: I keep my diary in a text file called “diary.txt”. I think my little brother is reading my diary. I’d like to encode it so he can’t read it. Creating a secret code (algorithmic) steps: 1. 2. 3. What should I call my program (class)? Declare variables. Repeat these steps: 1. 2. 3. 4. Read in a line. Encode a line. Write the encoded line. Finish up. Creating a secret code What is my secret code? How do I encode things? Consult Hollywood! “2001” movie Computer called HAL. What was HAL really? Creating a secret code What is my secret code? How do I encode things? Consult Hollywood! “2001” movie Computer called HAL. What was HAL really? “HAL” stands for “IBM” – they subtracted 1 from each character. We’ll adopt the same technique and make ‘B’ into ‘A’ … Encoding //ch below is a char (a character) char enc = ch; //no change by default //encode the characters if (ch=='a') enc = 'z'; else if (ch=='b') enc = 'a'; else if (ch=='c') enc = 'b'; … else if (ch=='z') enc = 'y'; Another way to encode What statement (other than ‘if’) did we see recently that can also be used for encoding? //ch below is a char (a character) char enc = ch; //no change by default //encode the characters switch (ch) { case 'a': enc = 'z'; case 'b': enc = 'a'; … case 'z': enc = 'y'; } break; break; break; //ch below is a char (a character) char enc = ch; //no change by default //encode the characters switch (ch) { case 'a': enc = 'z'; case 'b': enc = 'a'; … case 'z': enc = 'y'; } Switch expressions must always evaluate to integers. So how/why does this work? break; break; break; ASCII = American Standard Code for Information Interchange The characters are assigned numbers (integers). So we can use them in a switch. We can also add, subtract, multiply, and divide them! Given that, how can we make this less cumbersome? //ch below is a char (a character) //ch below is a char (a character) char enc = ch; //default = same char enc = ch; //default = same //encode the characters if (ch=='a') enc = 'z'; else if (ch=='b') enc = 'a'; else if (ch=='c') enc = 'b'; … //encode the characters switch (ch) { case 'a': enc = 'z'; break; case 'b': enc = 'a'; break; … } char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } How about uppercase letters? char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { //handle lowercase letters enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } Casts if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); The result of this expression is an int. } else { enc = ch; //unchanged } cast = convert from other types (int) to this type (char). Other useful casts. float f = (float)0.3; int i = (int)12.6; Causes truncation. What if I wanted to round? Casts and rounding double d = 0.9; int i1 = (int) d; int i2 = (int) (d+0.5); Back to our original problem: How can we use this to encode our diary? Algorithm: •What should I call my program (class)? •Declare variables. •Repeat these steps: •Read in a line. •Encode a line. •Write the encoded line. •Finish up. char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } Recall: Output contents of file to screen/window. //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); //perform encoding … //output encoded line System.out.println( s ); } in.close(); //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); //perform encoding char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } //output encoded line System.out.println( s ); } in.close(); How can we get ch from s? //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); char ch = s.charAt( 0 ); //perform encoding char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } //output encoded line System.out.println( s ); } in.close(); How can we get all of the chars from s? //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); Now we need to create an for (int i=0; i<s.length(); i++) { output string of encoded char ch = s.charAt( i ); chars. //perform encoding char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } } System.out.println( s ); //output encoded line } //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); We created an output //perform encoding string of encoded chars. char enc; if (ch=='a') { Finally, we need to write enc = 'z'; out the encoded } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); information to another file. } else { enc = ch; //unchanged } outLine = outLine + enc; } System.out.println( outLine ); //output encoded line } Here’s the complete program that writes the encoded information to another file. Don’t forget that you need a decoder program too! import import import import java.io.FileInputStream; java.io.FileOutputStream; java.io.PrintWriter; java.util.Scanner; //perform encoding char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; class Encode { public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); } out.println( outLine ); //output encoded line } out.close(); in.close(); } } TYPES OF FILES Types of files Text only contains lines of ASCII text can be viewed with text editors such as notepad easier to work with but less compact used in this course Binary very compact but you have to be privy to the format cannot be viewed with text editors not used in this course ANOTHER PROBLEM FOR DISCUSSION Problem for discussion You did a survey. You have a file containing numbers (integers) from a survey. Valid responses are in the range [1..10]. Write a program that reads in these numbers and determines their average. You may assume that the file only contains integers but some responses may not be valid (e.g., 0, -5, or 100). You should not include these values in the average. However, you should print a message like the following: Response number 22 is invalid, -7. YET ANOTHER PROBLEM FOR DISCUSSION Yet another problem for discussion You did another survey (of ages of people who voted in the last election). You keep the ages in a file. What is the min, max, and mean voting age? For extra credit, what is the mean voting age if you don’t count the min and max? (This is called the trimmed or truncated mean, http://en.wikipedia.org/wiki/Truncated_mean, or the interquartile mean, http://en.wikipedia.org/wiki/Interquartile_mean.)