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
Output to files reading: 6.4 1 Output to files • PrintStream: A class in the java.io package that lets you print output to a destination such as a file. – Any methods you have used on System.out (such as print, println, printf) will work on a PrintStream. • Syntax: File myFile = new File("file name"); PrintStream name = new PrintStream(myFile); OR OR PrintStream name = new PrintStream(new File("file name")); PrintStream name = new PrintStream("file name")); Example: PrintStream output = new PrintStream(new File("out.txt")); output.println("Hello, file!"); output.println("This is a second line of output."); Contents of file out.txt: Hello, file! This is a second line of output. 2 Details about PrintStream PrintStream name = new PrintStream(new File("file name")); PrintStream name = new PrintStream("file name"); – If the given file does not exist, it is created. – If the given file already exists, it is overwritten. – The output you print appears in a file, not on the console. You will have to open the file with an editor to see it. In Eclipse a new file will not automatically show up, you must right click on the project (e.g. Program8) and choose Refresh. – Do not open the same file for both reading (Scanner) and writing (PrintStream) at the same time. • You will overwrite your input file with an empty file (0 bytes). – If Java can't create or write the file it throws a FileNotFoundException. (e.g. If the path to the file does not exist or the name is not a legal file name in the system.) 3 PrintStream Objects • The console output object, System.out is a PrintStream object. PrintStream out1 = System.out; PrintStream out2 = new PrintStream(new File("data.txt")); out1.println("Hello, console!"); // goes to console out2.println("Hello, file!"); // goes to file – A reference to System.out can be stored in a PrintStream variable. • Printing to that variable causes console output to appear. – You can pass System.out to a method as a PrintStream parameter, using out1. • • • • Allows a method to send output to the console or a file. (This is rarely of use , and probably never of use in COS 160.) outputMethod(out1,”whenever”); // writes to System.out, the console. outputMethod(out2, “whatever”); // writes to file data.txt public static void outPutMethod(PrintStream chosen, String s){ chosen.println(s); } 4 import java.io.*; // for File public class Choose { public static void main(String[] args) throws FileNotFoundException { PrintStream out1 = System.out; PrintStream out2 = new PrintStream(new File("data.txt")); outputMethod(out1,"whenever"); // writes to System.out, the console. outputMethod(out2, "whatever"); // writes to file data.txt } public static void outputMethod(PrintStream chosen, String s) { chosen.println(s); } } Console: whenever data.txt: whatever 5 PrintStream question • Modify our previous Hours program to use a PrintStream to send its output to the file hours_out.txt. – The program will produce no console output. – But the file hours_out.txt will be created (or overwritten) with the text: Kim (ID#123) worked 31.4 hours (7.85 hours/day) Eric (ID#456) worked 36.8 hours (7.36 hours/day) Stef (ID#789) worked 39.5 hours (7.9 hours/day) 6 PrintStream answer // Processes an employee input file and outputs each employee's hours another file. import java.io.*; // for Files, also FileNotFoundException import java.util.*; // for Scanner public class Hours2 { public static void main(String[] args) throws FileNotFoundException { Scanner input = new Scanner(new File("hours.txt")); PrintStream out = new PrintStream(new File("hours_out.txt")); while (input.hasNextLine()) { Scanner lineScan = new Scanner(input.nextLine()); int id = lineScan.nextInt(); // e.g. 456 String name = lineScan.next(); // e.g. "Eric" double sum = 0.0; int count = 0; while (lineScan.hasNextDouble()) { sum = sum + lineScan.nextDouble(); count++; } double average = sum / count; out.printf("%s (ID# %d) worked %5.2f hours (%5.2f hours/day)\n", name, id, sum, average); } System.out.println("Job done, output written to file hours_out.txt.");}} Console: Job done, output written to file hours_out.txt. hours_out.txt: Kim (ID#123) worked 31.40 hours (7.85 hours/day) Eric (ID#456) worked 36.80 hours (7.36 hours/day) Stef (ID#789) worked 39.50 hours (7.90 hours/day) 7 import java.io.*; // for File import java.util.*; // for Scanner public class Overwrite { public static void main(String[] args) throws FileNotFoundException { File outFile = new File("out.txt"); You can use this test to allow the user to decide whether or if (outFile.exists()){ not to overwrite the file. PrintStream out = new PrintStream(outFile); System.out.println("File " + outFile.getName() + " existed and will be overwritten."); out.println("File " + outFile.getName() + " existed and was overwritten."); } else { System.out.println("File " + outFile.getName() + " does not exist and will be created and written to."); PrintStream out = new PrintStream(outFile); out.println("I did not exist but now I do"); } } } First run Console: File out.txt does not exist and will be created and written to. out.txt: I did not exist but now I do Second run Console: File out.txt existed and will be overwritten. out.txt: File out.txt existed and was overwritten. 8 Allowing the user to decide whether or not to overwrite an existing file. (version 2) Run1: Overwrite an existing file. Console: Enter a file name to use: bogus File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: grtyu File exists! Do you want to overwrite it? (yes/no) yes Wrote to file named: grtyu Run2: Create a new file and write to it. Console: Enter a file name to use: ffdre File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: grtyu File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: qqqq Wrote to file named: qqqq 9 • • Prompting for a file name Done in exactly the same way as getting a file name for input. Use nextLine(), not next() – File name may contain spaces. // prompt for input file name Scanner console = new Scanner(System.in); System.out.print("Enter a file name to use: "); String filename = console.nextLine(); File file = new File(filename); If the file does not exist at any point, we assume it is OK to write to it. // See if the user wants to overwrite an existing file boolean overwriteFile = false; while (file.exists()) { System.out.print("File exists! Do you want to overwrite it? (yes/no) "); String yesNo = console.nextLine(); if (yesNo.equalsIgnoreCase("yes")) . . . // (see next slides) 10 while (file.exists()) { // From previous slode. System.out.print("File exists! Do you want to overwrite it? (yes/no) "); String yesNo = console.nextLine(); if (yesNo.equalsIgnoreCase("yes")){ overwriteFile = true; break;} else if (yesNo.equalsIgnoreCase("no")){ System.out.print("Enter a different file name to use: "); filename = console.nextLine(); file = new File(filename); } else // yes or no not entered System.out.print("Please enter yes if you want to overwrite the file" + " and no if you do not: "); } PrintStream out = new PrintStream(file); out.println("Whatever"); System.out.println("Wrote to file named: " + filename); } } } 11 import java.io.*; import java.util.*; // not recommended, need space to fit program on slide public class FileExists { public static void main(String[] args) throws FileNotFoundException { Scanner console = new Scanner(System.in); System.out.print("Enter a file name to use: "); String filename = console.nextLine(); File file = new File(filename); boolean overwriteFile = false; while (file.exists()) { System.out.print("File exists! Do you want to overwrite it? (yes/no) "); String yesNo = console.nextLine(); if (yesNo.equalsIgnoreCase("yes")){ overwriteFile = true; break;} else if (yesNo.equalsIgnoreCase("no")){ System.out.print("Enter a different file name to use: "); filename = console.nextLine(); file = new File(filename); } else // yes or no not entered System.out.print("Please enter yes if you want to overwrite the file" + " and no if you do not: "); } PrintStream out = new PrintStream(file); out.println("Whatever"); System.out.println("Wrote to file named: " + filename); 12 } } Allowing the user to decide whether or not to overwrite an existing file. (version 2) Console: Enter a file name to use: other.txt File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: iuty File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: q125 Creating and writing to new file q125 Contents of file q125 I feel brand new. Console: Enter a file name to use: other.txt File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: q123 File exists! Do you want to overwrite it? (yes/no) yes Overwriting file q123 Contents of file q123 I have been overwritten. 13 File writing program, page 1 import java.io.*; import java.util.*; public class FileExistsWhile { public static void main(String[] args) throws FileNotFoundException { Scanner console = new Scanner(System.in); First time encountering the loop, if System.out.print("Enter a file name to use: "); file.exists() is false then the while is String filename = console.nextLine(); not executed at all. This condition File file = new File(filename); may also occur after the loop has boolean overwriteFile = false; executed several or many times while (file.exists() && !overwriteFile) { System.out.print("File exists! Do you want to overwrite it? (yes/no) "); String yesNo = console.nextLine(); if (yesNo.equalsIgnoreCase("yes")) overwriteFile = true; else if (yesNo.equalsIgnoreCase("no")){ System.out.print("Enter a different file name to use: "); filename = console.nextLine(); file = new File(filename); } else // yes or no not entered System.out.print("Please enter yes if you want to overwrite the file” + “ and no if you do not: "); } more . . . 14 File writing program, page 2 /* When we exit the loop it could be for 1 of 2 reasons: 1. Found a file that did not previously exist. 2. Want to overwrite a file. It is very common in programming to test which condition caused a loop to exit after it has exited. */ PrintStream out = new PrintStream(file); if (overwriteFile){ System.out.println("Overwriting file " + file.getName()); out.println("I have been overwritten."); } else { System.out.println("Creating and writing to new file " + file.getName()); out.println("I feel brand new."); } } } Run 1: try.txt does not exist. Enter a file name to use: try.txt Creating and writing to new file try.txt try.txt: I feel brand new. Run2: try.txt exists Enter a file name to use: try.txt File exists! Do you want to overwrite it? (yes/no) yes Overwriting file try.txt try.txt: I have been overwritten. 15 Run 3: User does not want to overwrite an existing file. Enter a file name to use: try.txt File exists! Do you want to overwrite it? (yes/no) qw Please enter yes if you want to overwrite the file and no if you do not: File exists! Do you want to overwrite it? (yes/no) re Please enter yes if you want to overwrite the file and no if you do not: File exists! Do you want to overwrite it? (yes/no) no Enter a different file name to use: slop Creating and writing to new file slop slop: I feel brand new. Note: The only way to quit this program is to accept one of the options. A test should be added that allows the user to type quit in order to stop without writing to a file. 16 Example: Creating a file of powers of 2 import java.io.*; // for File import java.util.*; // for Scanner public class PowersOfTwo { public static void main(String[] args) throws FileNotFoundException { File f = new File("powersOf2.txt"); powersOf2.txt PrintStream output = new PrintStream(f); output.println("powers of 2"); powers of 2 int power = 1; 2^1 = 2 for (int i = 1; i <= 10; i++) { 2^2 = 4 power *= 2; 2^3 = 8 output.printf("2^%-2d = %4d\n", i, power); 2^4 = 16 } 2^5 = 32 } 2^6 = 64 } What happens if a file names powersOf2.txt already exists? 2^7 2^8 2^9 2^10 = 128 = 256 = 512 = 1024 It will be overwritten. 17 Activity • Write a program to read a file and then create a ">" indented output file as when quoting a mail message. Input file: Output file: Sue, la de dah de dah de dah Thanks, Bob > Sue, > la de dah > de dah > de dah > Thanks, > Bob Here is a start: public static void main(String[] args) throws FileNotFoundException { Scanner consoleIn = new Scanner(System.in); System.out.print("Input file: "); String inFilename = consoleIn.nextLine(); System.out.print("Output file: "); String outFilename = consoleIn.nextLine(); 18 import java.io.*; import java.util.*; public class echoFile { public static void main(String[] args) throws FileNotFoundException { Scanner consoleIn = new Scanner(System.in); System.out.print("Input file: "); String inFilename = consoleIn.nextLine(); Console: File inFile = new File(inFilename); Input file: Sue.txt Scanner inputFile = new Scanner(inFile); Output file: outSue.txt Finished copying file Sue.txt to outSue.txt System.out.print("Output file: "); String outFilename = consoleIn.nextLine(); File outFile = new File(outFilename); PrintStream outputFile = new PrintStream(outFile); String myString; Sue.txt Sue, la de dah de dah de dah Thanks, Bob outSue.txt >Sue, >la de dah >de dah >de dah >Thanks, >Bob while ( inputFile.hasNextLine() ) { myString = inputFile.nextLine(); outputFile.println(">" + myString); } System.out.println("Finished copying file “ + inFilename + " to " + outFilename); } } 19 • More on the exists() method: /*This program is looking to open an existing import java.io.*; file and then read it. It rejects all files that do import java.util.*; not exist (are not found).*/ public class FileExistsWhile { public static void main(String[] args) throws FileNotFoundException { Scanner console = new Scanner(System.in); Why must we say the method System.out.print("Type a file name to use: "); throws the FileNotFoundException? String filename = console.nextLine(); File file = new File(filename); It can’t throw the exception while (!file.exists()) { because we test for the file’s System.out.print("File not found! Try again: "); existence but the compiler does not know this. The compiler must filename = console.nextLine(); see a try catch block to know the file = new File(filename); exception was handled. } Scanner input = new Scanner(file); // open the file }} 20 Output: Type a file name to use: hourz.text File not found! Try again: h0urz.txt File not found! Try again: hours.txt When writing a file you might not want to overwrite an existing file: String fileName; Scanner console = new Scanner(System.in); System.out.print("Enter a file name: "); fileName = console.next(); File f = new File(fileName); while ( f.exists() ) { System.out.println("File " + fileName + " exists, do you want to overwrite it? " + "(Enter yes or no)"); /*This program reads the name of an String yesNo = console.next(); output file and tests to see if it already if (yesNo.equalsIgnoreCase("yes")) exists. If it does it asks the user if they break; // used break instead of boolean want to overwrite the file. If the answer is yes, the file is overwritten, if System.out.print("Enter a new file name: "); the answer is anything other than yes fileName = console.next(); it is taken as a no, a new file name is f = new File(fileName); read and the process repeats until a } satisfactory file name is entered. PrintStream output = new PrintStream(f); */ output.println("powers of 2"); int power = 1; for (int i = 1; i <= 10; i++) { power *= 2; output.printf("2^%-2d = %4d\n", i, power); } }} 21 System.out.println(“File “ + fileName + “now contains the powers of 2.”); File pwrs2.txt does not exist before this sequence. Enter a file name: asdf.txt File asdf.txt exists, do you want to overwrite it? (Enter yes or no) no Enter a new file name: ffdre File ffdre exists, do you want to overwrite it? (Enter yes or no) ye // This is taken as a no. Enter a new file name: qwer File qwer exists, do you want to overwrite it? (Enter yes or no) yeah // This is taken as a no. Enter a new file name: pwrs2.txt File pwrs2.txt now contains the powers of 2. pwrs2.txt powers of 2 2^1 = 2 2^2 = 4 2^3 = 8 2^4 = 16 2^5 = 32 2^6 = 64 2^7 = 128 2^8 = 256 2^9 = 512 2^10 = 1024 Now pwrs2.txt exists so another run might look like this: Enter a file name: asdf.txt File asdf.txt exists, do you want to overwrite it? (Enter yes or no) no Enter a new file name: pwrs2.txt File pwrs2.txt exists, do you want to overwrite it? (Enter yes or no) Yes File pwrs2.txt now contains the powers of 2. 22 Scanner console = new Scanner(System.in); Same program as the last but System.out.print("Enter a file name to use: "); no break; statement and String filename = console.nextLine(); explicitly asks for “no”. File file = new File(filename); boolean overwriteFile = false; while (file.exists() && !overwriteFile) { System.out.print("File exists! Do you want to overwrite it? (yes/no) "); String yesNo = console.nextLine(); Enter a file name to use: good.txt if (yesNo.equalsIgnoreCase("yes")) File exists! Do you want to overwrite it? (yes/no) no overwriteFile = true; Enter a different file name to use: good.txt else if (yesNo.equalsIgnoreCase("no")){ File exists! Do you want to overwrite it? (yes/no) yes Overwriting file good.txt System.out.print( "Enter a different file name to use: "); filename = console.nextLine(); file = new File(filename); } else System.out.print("Please enter yes if you want to overwrite the file and no if you do not:\n "); } PrintStream out = new PrintStream(file); if (overwriteFile){ System.out.println("Overwriting file " + file.getName()); out.println("I have been overwritten."); } else { System.out.println("Creating and writing to new file " + file.getName()); out.println("I feel brand new."); 23 } } Scanner console = new Scanner(System.in); System.out.print("Enter a file name to use: "); Same program as the last but String filename = console.nextLine(); uses a do while statement. File file ; boolean overwriteFile = false; do { file = new File(filename); if (file.exists()){ System.out.print("File exists! Do you want to overwrite it? (yes/no) "); String yesNo = console.nextLine(); if (yesNo.equalsIgnoreCase("yes")) overwriteFile = true; else if (yesNo.equalsIgnoreCase("no")){ System.out.print("Enter a different file name to use: "); filename = console.nextLine(); file = new File(filename); } else System.out.print( "Please enter yes if you want to overwrite the file and no if you do not: "); } } while ( !(!file.exists() || overwriteFile)) ; PrintStream out = new PrintStream(file); if (overwriteFile){ System.out.println("Overwriting file " + file.getName()); out.println("I have been overwritten."); } else { 24 System.out.println("Creating and writing to new file " + file.getName()); Handling the FileNotFoundException (Ignore if not enough time) • Java provides a method for handling exceptions called a try/catch statement (or try/catch block); try { // contains statements that can throw a FileNotFoundException <statement>; <statement>; FileNotFoundException ... <statement>; } catch (FileNotFoundException e) { <statement>; // These statements should take care of the <statement>; // exception. In Lab 9 we will read a default file ... // in but that did not really get rid of the error. <statement>; // That default file might not be there, either, / // so main() had to include a throws clause. } 25 import java.io.*; import java.util.*; public class FileGoodNameCatch { Type a file name to use: tyuiop FILE NOT FOUND: Please try again. Type a file name to use: tryew FILE NOT FOUND: Please try again. Type a file name to use: input.txt The quick brown fox jumps over the lazy dog. public static void main(String[] args) { Scanner console = new Scanner(System.in); Scanner input = null; File file; do{ System.out.print("Type a file name to use: "); String filename = console.nextLine(); file = new File(filename); try { input = new Scanner(file); // If this works, input will be set to a legal address } catch (FileNotFoundException e){ System.out.println("FILE NOT FOUND: Please try again."); } } while (input == null ); We do not need a throws while ( input.hasNext()) FileNotFoundException in main( System.out.println(input.next()); because that exception is } caught in main(). } 26 import java.io.*; import java.util.*; public class FileGoodName { Type a file name to use: tyuiop Type a file name to use: trvew Type a file name to use: input.txt The quick brown fox jumps over the lazy dog. public static void main(String[] args) throws FileNotFoundException { Scanner console = new Scanner(System.in); File file; do{ System.out.print("Type a file name to use: "); String filename = console.nextLine(); file = new File(filename); } while (!file.exists()); Scanner input = new Scanner(file); while ( input.hasNext()) System.out.println(input.next()); } We do need a throws FileNotFoundException in main() because the exception } is not caught in main(), no try … catch block. The logic says things are OK but the compiler does not see the logic. Actually there is at least one way to have Java throw an exception here. 27 // This example does nothing if the exception is thrown, but all is OK due to the program logic. // If you include a try/catch block, the compiler assumes you are handling the exception. // You wouldn’t lie to the compiler, would you? Type a file name to use: tyuiop import java.io.*; Type a file name to use: wertghj import java.util.*; Type a file name to use: input.txt public class FileGoodNameCatchLying { The quick public static void main(String[] args) { brown Scanner console = new Scanner(System.in); fox Scanner input = null; jumps File file; over do{ the System.out.print("Type a file name to use: "); lazy String filename = console.nextLine(); dog. file = new File(filename); try { input = new Scanner(file); // If this works, input will be set to a legal address } Initializing input to null is like initializing a catch (FileNotFoundException e){ boolean to false. If a file is not found, input is } not changed from the null value. We can test } while (input == null ); // Saved by this test. for that and continue until input is not null, while ( input.hasNext()) System.out.println(input.next()); meaning a file has been found that will work. input will contain a pointer (reference) to the Scanner object, that value is guaranteed28to not be null. import java.io.*; import java.util.*; public class FileGoodNameCatchBad { public static void main(String[] args) { Scanner console = new Scanner(System.in); Scanner input = null; File file; } } Console when a good file name is used: Type a file name to use: input.txt The quick brown fox jumps over the lazy dog. System.out.print("Type a file name to use: "); String filename = console.nextLine(); file = new File(filename); try { input = new Scanner(file); // If this works, input will be set to a legal address } Console when a bad file name is used: catch (FileNotFoundException e){ Type a file name to use: qwedcv } Exception in thread "main" while ( input.hasNext()) java.lang.NullPointerException at System.out.println(input.next()); FileGoodNameCatchWorse.main(FileGoo The existence of the catch block says that the exception is being handled. The machine believes it even though it is not true. Would a human lie? dNameCatchBad.java:17) This does not work because this statement throws the exception and it is 29 not in a try catch block.