LECTURE NOTES CHAPTER 16 READING AND WRITING TEXT FILES - text file - created w/ a simple text editor - e.g. Notepad .txt files, Java source, HTML files - ASCII or Unicode - read text from a file - java.io.FileReader(String fileName) throws java.io.FileNotFoundException - attach a reader to fileName - exception thrown if no file with that name exists - e.g. #1 FileEg.java - use FileReader to construct a Scanner object - Scanner(Readable source) - FileReader implements Readable - use Scanner methods to read text from input file - e.g. #2 FileEg.java - void FileReader::close() throws java.io.IOException - write text to a file - java.io.PrintWriter(String fileName) throws FileNotFoundException - attach a writer to fileName - if file already exists, old contents are deleted before new data is added - if file doesn't exist, empty file is created - exception thrown if no file with that name exists - e.g. #3 FileEg.java - use print and println methods to write data - convert numbers to their decimal string representations - use the toString method to convert objects to strings - void PrintWriter::close(): ensure output makes it to file - e.g. #4 FileEg.java - backslashes in file names - backslash is the escape character in strings - when creating a string in code, use the character '\\' to represent a literal backslash - java.io.File class - object to represent a file - File(String pathname) - creates a File object to represent a file at pathname - e.g. File inputFile = new File("input.txt"); - contains methods to delete and rename a file - boolean File::exists() - does not have to exist - test for existance - pass File object to output stream or writer to create - public FileReader(File file) throws FileNotFoundException - public PrintWriter(File file) throws FileNotFoundException - cannot use directly for reading or writing - e.g. read from a File object FileReader in = new FileReader(inputFile); AT 16.2 COMMAND LINE ARGUMENTS - invoking program from command line: starting program by typing its name in a terminal/shell window - command line arguments - specify additonal input to program on invocation - type each one, whitespace delimited, after the program name - placed in the args parameter of the main method - program determines how to interpret input - customary - strings starting with a hyphen as options - other strings as file names - GUI better for casual and infrequent user - GUI hard to automate: can use shell scripts to automate command line input INTERGER INPUT - method 1 - the number you're getting is the only thing on the line you need - String Scanner::nextLine(): returns user input as a String - static int Integer::parseInt(String s) throws java.lang.NumberFormatException - converts s to an int - unchecked exception thrown if string is not valid integer format - e.g. String input = scanner.nextLine(); int number = Integer.parseInt(input); - method 2 - need to use other data after the number on the same line - int Scanner::nextInt() throws java.util.InputMismatchException - returns next input data available as int value - if next input is valid integer format - unchecked exception thrown if input not valid integer format - e.g. int number = scanner.nextInt(); STREAMS - store info needed to connect IO device and program - add functionality to output streams - IO streams automatically created by java.lang.System - public static - java.io.InputStream System.in - generally, store info about the connection between an input device and the program - specifically, standard input device - java.io.PrintStream class: print and println - overloaded - work with any kind of data - specific instances: display to screen - System.out - System.err FILE INPUT EXAMPLES /* using File instead of FileReader */ System.out.print( "Enter the filename: " ); // Prompt the user for a file name String fileName = scanner.nextLine(); // get a file name from the user java.io.File file = new java.io.new File( fileName ); // create a File object if ( file.exists() ) // check that the file exists { // before trying to create a // Scanner to read the file // Create a Scanner from the file java.io.Scanner inFile = new java.io.Scanner( file ); // For each line in the file, read in the line and // display it with the line number int lineNum = 0; // Use the results of calling the hasNext method to // determine if you are at the end of the file before // reading the next line of the file. // If you use nextLine when there's no more data, // you'll get an unchecked java.lang.NoSuchElementException while ( inFile.hasNext() ) { line = inFile.nextLine(); // read the next line // Output the line read to the screen for the user System.out.println( ++lineNum + ": " + line ); } // When we're done reading the file, // close the Scanner object attached to the file inFile.close(); } STRING TOKENIZER - read data from text file to create objects - commonly - place all data for one object on same line - separate each item with delimiter (special character) - interpret certain parts of each line differently - e.g. student test scores Smith, Jill:87:82:95 Lee, Michael:82:89:92 Duck, Daffy:93:96:100 - tokenizing: split line of text into different parts - token: one such resulting piece - java.util.StringTokenizer - StringTokenizer(String str, String delim) - str is the String to tokenize - each character of delim is treated as a delimiter - boolean hasMoreTokens() - return true if any remaining tokens to process - String nextToken() - return next token as String object - throws unchecked java.util.NoSuchElementException if called when no tokens remaining - int countTokens() - return number of remaining tokens available to the current instance - e.g. // Make sure that the file student_scores.txt exists and has // valid data records. Otherwise, exceptions will occur. File gradeFile = new File( "student_scores.txt" ); if ( gradeFile.exists() ) { // Create the buffered reader for reading the file Scanner inFile = new Scanner( gradeFile ); // If line is not end of file continue while ( inFile.hasNext() ) { // Get the first line of the file String line = inFile.nextLine(); // Create a StringTokenizer with a colon sign as a delimiter java.util.StringTokenizer st = new java.util.StringTokenizer( line, ":" ); // Display the content of the first token System.out.print( " Name: " + st.nextToken() ); // Display the total number of tokens remaining this string int numScores = st.countTokens(); // Initialize the sum to zero int sum = 0; // Get each score, add it to the sum and print it for ( int i=1; i <= numScores; i++ ) { int score = Integer.parseInt( st.nextToken() ); sum += score; } // Display the average score for this student System.out.println( " average = " + sum/numScores ); } // end while not at end of file // Close the Scanner inFile.close(); } // end if the grade file doesn't exist ALTERNATE METHODS FOR FILE OUTPUT - what to do if file already exists - best to ask user to choose - overwrite - different name - cancel - java.io.FileWriter extends OutputStreamWriter extends Writer - open a file and connect an output stream to it - FileWriter(String fileName, boolean append) - fileName is the name of the file to be written - if append, write to end of the file instead of overwriting - throws IOException if file can't be accessed or created - deletes old contents first (overwrites file) if already exists - avoid by - creating a File object - testing it for existence - flushing - expensive to access disk - relatively inexpensive to continue to accessing disk sequentially - reduce cost of writing - batching: perform several all at once - buffering: temporarily store in memory until have enough to batch write - flush: - specifically force writes to go all the way to disk - write everything currently in the buffer - more PrintWriter functionality - PrintWriter(Writer out, boolean autoFlush) - out is a stream to write to - if autoFlush, calls to println (but not print) will be flushed - void flush() - force the buffer to disk - throws IOException if some error occurs while trying to do so - e.g. // Create a FileWriter attached to a file named "out.txt". // The second parameter sets whether or not new data // will be appended to the end of the file or the beginning. // false means that this file will be overwritten. java.io.FileWriter fw = new java.io.FileWriter( "out.txt", false ); // Create a PrintWriter that automatically flushes data // to the output file whenever the println method is used. java.io.PrintWriter pw = new java.io.PrintWriter( fw, true ); // Buffer some data to write to the file (doesn't actually write until flush) pw.print( "Some test data that will be written when flush is called."); // Flush all buffered data to the file. pw.flush(); // Write some data and automatically flush it to the file. pw.println( data ); // Close the PrintWriter for added safety. pw.close(); 16.3 AN ENCRYPTION PROGRAM - encryption: scrambles a file so it is unreadable except to those who know the decryption method and secret keyword - Caeser Cipher - shift letters by some amount between 1 and 25 - decrypt by shifting by -(key)