590 likes | 602 Views
Learn the difference between files and streams, read/write files using Scanner and PrintWriter. Discover how to handle file streams effectively and close them properly. Explore the significance of file handling in Java programming.
E N D
Outcomes • Know the difference between files and streams • Use a Scanner to read from a file • add “throws” annotations to methods • use the hasNext family of methods to read every element in a file • Use a PrintWriter object to write to a file • Know when and why to close file streams • how to use autoclose to ensure they get closed • Know how to read an entire text file
System.in (kbd) System.out Input & Output Streams • System.in and System.out are streams • carry information from one place to another • System.in: from keyboard to program • System.out: from program to monitor keyboard Program monitor
fin (Scanner) fout (PrintWriter) fileIn.txt myprog.exe fileOut.txt File Streams • Can get program to read from/write to files • connect Scanner to a file instead of System.in • use a PrintWriter instead of System.out • carry information to/from files
Streams and Files • File exists as a whole, on the disk (or key) • Stream just connects it to the program • data comes in/goes out in pieces 3Numbers.txt SumOf3.txt Read3NumbersFromFile.class fout fin Scanner PrintWriter Input File Output File Program
Streams and Files • File exists in secondary memory • File has a name • Data is in the file • Scanner carries the data 3Numbers.txt Read3NumbersFromFile.class
(Possible) Program Variables • A String variable for the file name • A File variable for the file • A Scanner variable for the Scanner • Variable(s) for the data “3Numbers.txt” 3Numbers.txt Read3NumbersFromFile.class
Text Files • We will only read from text files • have .txt extension on a Windows system • tho’ Windows may hide it from you! • Text files can contain numbers (numerals) • and may contain only numbers 10 15 340 -7 -2 103 Twasbrillig and the slithytoves 3Numbers.txt poem.txt
Why Use Files? • Permanence • can re-use input; don’t need to copy output • can use output of one program as input to next • Accuracy • correct before the program gets it • even “invisible” output characters stored • Ease of use • large quantities of input hard to type correctly
Using Files • Need to import some classes import java.util.Scanner; import java.io.PrintWriter; import java.io.File; import java.io.FileNotFoundException; • File I/O like console I/O, except: • file streams need to be declared • file streams need to be opened before use • file streams should be closed when done • there are pesky “exceptions” to deal with
Declaring File Streams • Create a file stream ScannerinStream; input file stream(*) PrintWriteroutStream; output file stream(*) • Typical names for file stream variables in, fin, inStream, inFile out, fout, outStream, outFile • also names that suggest the file contents stuNumFile, encodedFile, …
(*) File Streams • There are actually classes called InputFileStream and OutputFileStream • these are the very basic file streams • they’re not very useful (for us) • Also lots of other kinds of file streams • useful for different kinds of tasks • Scanners and PrintWriters are more useful for the kinds of things we want to do
Using File Streams • Our input streams are Scanner objects int n = fileIn.nextInt(); String line = fileIn.nextLine(); • fileIn acts just like kbd • Our output streams are PrintWriter objects fileOut.println("The number you entered was " + n); fileOut.print("The line was: '" + line + "'\n"); • fileOut acts very much like System.out Actually, System.out is a PrintStream, not a PrintWriter. PrintWriters are “new and improved” PrintStreams.
Opening a File for Input • Create a String object for the file’s name String fileName = "3Numbers.txt"; • Create a File object to represent the file File dataFile = new File(fileName); • Create a Scanner to read data from the file Scanner fin = new Scanner(dataFile); • Or combine it all into one command Scanner fin = new Scanner(new File("3Numbers.txt")); NOTE: new File(…) does not mean that the file is new! We’re just creating a newobject to represent that file.
Files & Folders • Files exist inside folders • J:\ NetBeans Projects\Lab03\src\myProg.java • J:\ NetBeans Projects\Lab05\Lab05Data.txt src Lab03 myProg.java NetBeans Projects J: myProg.class classes Lab05Data.txt Lab05
Files & Folders • If you just give the name of the file… • myData.txt • …then looks in the project folder • not the src folder! • But you can specify other folders • absolute/relative paths src Lab03 Looks here… …not there
File Paths • Somewhat system dependent • but can always use / to separate folder names • remember to “escape” \ if inside quote marks • Absolute path • J:/JCreator LE/Lab05/Lab05Data.txt • Relative path (from L03 folder) • ../Lab05/Lab05Data.txt
File Paths • Use / in Strings in your code • will work on any machine, not just Windows • “..” means the folder my folder is in • “../..” means the folder that it’s in • and so on! • Put data files in project folder • Use relative paths Lab03 NetBeans Projects J: Project Folder .. ../..
Problem • An error message when we try to open a file • “… java.io.FileNotFoundExceptionmust be caught or declared to be thrown” • FNFExn is not a RuntimeException • RuntimeExceptions are nicer • don’t need to say you’re not catching them • need to say you’re not catching FNFExn • or, you know, actually catch it
Declaring an Exception • Say you’re not catching it public static void main(String[] args) throws FileNotFoundException { • NOTE where it is – before the body’s opening brace • Note: throws instead of throw • throw is a command • tells computer to do something • throws is a description • says what this method sometimes does
When to Use a throws Clause • Use throws FileNotFoundException in • any method that opens a file (without catching) • input or output • any method that calls any method that has that throws clause (and doesn’t catch) public static void doFileIO()throws FileNotFoundException{ ... } public static void main(String[] a)throws FileNotFoundException { doFileIO(); } • doFileIO may throw FNFExn; main won’t catch it
Example (Part 1) import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; public class Read3NumbersFromFile { public static void main(String[] args) throws FileNotFoundException { int n1, n2, n3; Scanner fin = new Scanner(new File("3Nums.txt")); Continued next slide…
Example (Part 2) n1 = fin.nextInt(); n2 = fin.nextInt(); n3 = fin.nextInt(); System.out.println("The numbers in the file are: " + n1 + ", " + n2 + ", and " + n3); } } • no fin.nextLine(). Why not? • don’t expect file creator to press the enter key!
Names of Objects • Name of the file itself: 3Nums.txt • the file has the numbers in it • Name of the Scanner: fin • the Scanner is “attached” to the file • gets input from the file instead of from the user • Don’t get them confused: int n1 = 3Nums.txt.nextInt(); • errors: illegal name/unknown name
Exercise • Modify the previous program to read four numbers and print their sum • 3Nums.txt actually has four numbers in it. • Last value is a sentinel (see next slide)
Javadoc @throws Tag • Add @throws tag to javadoc comment • says that this method throws an exception • says what kind(s) of exception it throws • says why it might be thrown /** * … * @throws FileNotFoundException if 3Nums.txt cannot be found */
Reading a Whole File • Suppose list of numbers is in a file • How shall we read the whole list? • ask user how many numbers in file? • have file start with many numbers it has? • end file with “sentinel” value? • But even better: • we can ask the Scanner • it can check to see if there are more numbers!
Ask the Scanner • Can ask Scanner if file has more data • hasNextInt(), hasNextDouble(), … fin = new Scanner(new File("3Nums.txt")); double sum = 0.0; while(fin.hasNextDouble()) { sum += fin.nextDouble(); } System.out.println("The sum of the #s in the file is " + sum);
The hasNext Family • There’s a “hasNext” for each “next” • nextDouble hasNextDouble • will nextDouble work? • nextInt hasNextInt • will nextInt work? • next hasNext • nextLine hasNextLine • hasNext... just checks if it’s there • you have to use next... to read it
Exercise • Write a program fragment to • open “MyEssay.txt” for input • count the number of words in it • report the number of words to the user
File Output • Just like file input, except: • use PrintWriter instead of Scanner • imported from java.io, not java.util • use print & println instead of next, nextInt, &c. • just like System.out import java.io.PrintWriter; PrintWriterfout = new PrintWriter(new File("t.txt")); fout.println("..."); // print to t.txt
Exercise • Modify the number summing program to send the output to the file Summary.txt
Problem • We open the file for output • We write the sum to the file • But when we look at the file, it’s empty! • Why? Buffering! • takes a long time to find the place to print, but then the printing itself is (relatively) fast • PrintWriter saves up output till it has lots • But if the program ends before it prints it out….
Closing Streams • Need to tell the PrintWriter when you’re done printing stuff to the file • so it knows to send what’s remaining to the file fout.close(); • You should also close Scanners when you’re done with them • frees up the file and system resources fin.close();
Output Files Start Empty • Output files get created if they didn’t already exist • If an output file did already exist, its contents get erased • once you open it (don’t need to print to it) • If you want to add to the old file PrintWriterfout = new PrintWriter(new FileOutputStream("out.txt", true));
Reading File Names • Can mix file and user i/o • e.g. ask user for the name of the file Scanner kbd = new Scanner(System.in); System.out.print("Enter name of file: "); String fileName = kbd.nextLine(); Scanner fin = new Scanner(new File(fileName)); int n1 = fin.nextInt(); • Reads file name from user • Reads int value from the named file
Exercise • Revise the summing program to read the name of the file the numbers are in • use 3Nums.txt, 100Nums.txt, 1000Nums.txt • use a file that doesn’t exist. What happens? • Revise it again to ask for the output file • use a file that doesn’t already exist • use a file that does already exist • what happens?
Read and Save a File’s Data • When reading from a file, you often don’t know how many elements there will be • use an ArrayList to store the data • Loop until file ends, adding elements while (fin.hasNext()) { myWords.add(fin.next()); } • reads all the words of that file into myWords • don’t need to check for filled array
Reading All Numbers from a File • Loop until no more numbers • remember to use wrapper class ArrayList<Double> myNumbers = new ArrayList<Double>(); Scanner fin = new Scanner(new File(fileName)); while (fin.hasNextDouble()) { myNumbers.add(fin.nextDouble()); } fin.close(); • (still need to catch/declare FileNotFoundException)
Exercise • Revise this code to read integer values instead of doubles ArrayList<Double> myNumbers = new ArrayList<Double>(); Scanner fin = new Scanner(new File(fileName)); while (fin.hasNextDouble()) { myNumbers.add(fin.nextDouble()); } fin.close();
The File Class • Why do we write “new File(…)”? • it’s not always a new file, after all! • Creating a File object • a program object to represent the file • (remember, the Scanner/PrintWriter is for communicating with the file) • actually just holds the name of the file, but… • …it knows it’s supposed to be the name of a file
Yet Another Variable • You can create a variable for the File File f = new File(fileName); • You can ask the File object about the file • does this file exist? f.exists() • can we read from it? f.canRead() • can we write to it? f.canWrite() • is it a folder/directory? f.isDirectory() • and more these methods may throw SecurityExceptions, but they don’t need to be checked (they are RunTime Exceptions)
Getting a Readable File • Keep asking for file names until we get one that says it’s readable String fileName; File f; do { System.out.print("Enter a readable file name: "); fileName = kbd.nextLine(); f = new File(fileName); } while (!f.canRead());
But Still Need to Catch… • Knowing that a file is readable/writable doesn’t mean you can skip the try/catch • file could get deleted between the time you ask if it’s readable and the time you try to create the Scanner/PrintWriter!
Catching FNFExn • Can use a try-catch block, of course try { … } catch (FileNotFoundExceptionfnf) { … } • Questions: • Where to put it? • What goes inside the try block?
File Not Found Exceptions • In file i/o we have FileNotFoundExceptions • generated when try to create a Scanner • or a PrintWriter • What do we want to happen? • end the program (gracefully!) • give user another chance • maybe after 3 chances end the program • use a default file or value
End the Program • Catch block should also print error message try { System.out.print("Enter file name: "); Scanner fin = new Scanner(new File(fileName)); // read from the file using fin here fin.close(); } catch (FileNotFoundExceptionfnf) { System.err.println("File not found. Quitting."); System.exit(1); } Error message (just before System.exit) should be printed to System.err instead of System.out.
System.exit • End the program • takes one argument: program return code • System.exit(0) everything finished fine • System.exit(1) something went wrong • System.exit(2) something (else) went wrong • System.exit(3) something (else else) ... • Usually only need (0) and (1) • otherwise NAME your return codes (finalvars)
Exercise • Revise this code to exit program if the file SecretPlanet.txt can’t be found public Planet ReadPlanetFromFile() throws FileNotFoundException { Scanner fin = new Scanner(new File("SecretPlanet.txt")); String aName = fin.nextLine(); intaCode = fin.nextInt(); double aDist = fin.nextDouble(); fin.close(); return new Planet(aName, aDist, aCode); }
Give User Another Chance • Print warning message and try again • need a loop with try-catch block inside it Scanner fin = null; while (fin == null) { try { System.out.print("Enter file name: "); String name = kbd.nextLine(); fin = new Scanner(new File(name)); } catch (FileNotFoundExceptionfnf) { System.out.println("Not found! Try again."); } } // read from the file using fin down here