File IO (1-26)

advertisement
File IO
Includes Exceptions
Topics

General concepts





Throw an exception
Create your own Exception
(NegativeBalanceException)
Select a file (LineNumberer)





Exception handling
Creating a file in Eclipse
Use of Scanner class

Hard-code name
Accept from keyboard
File Chooser
Command Line
Exceptions (FileTotal)


throws clause
try/catch
Be prepared for two quick exercises
– start Eclipse now! Create a
project named ExceptionsDemo
Handling Errors
try – prepare to execute statement that
might yield an error
error – exception is thrown
success – continue on
You need to think about:
• what statements might cause errors?
• how to handle an error that occurs
error – exception is caught
Prepare to read


FileReader is used to read data from file
Test to ensure you can find the file.
FileReader reader = new FileReader(“in.txt”);

Wrap the FileReader in a Scanner object (pass the
FileReader to the constructor)
Scanner in = new Scanner(reader);

Handle errors in data format.
Scanner
“in.txt”
FileReader
FileReader
String
int
double
etc.
Prepare for output
•
Use PrintWriter. (from documentation):
•
•
•
•
•
Print formatted representations of objects to a text-output
stream.
Implements all of the print methods found in PrintStream.
Does not contain methods for writing raw bytes.
If automatic flushing is enabled it will be done only when one
of the println() methods is invoked.
Methods include println (variety of parameters), write, close,
flush, checkError (no exceptions thrown, must check for
errors).
Let’s get started – create a file



We’ll create a simple text file within Eclipse.
Choose File->New->Untitled Text (or just file)
Be sure to save in the project – not inside a package
Line Numberer


Read an input file
Write the lines, with line numbers, to an output file
LineNumberer – basic structure


We will need names for both the input and output files
We’ll see 4 different ways to do this. For now, set up
variables.
public class LineNumberer {
private String inputName;
private String outputName;
public void setOutputName(String outputName) {
this.outputName = outputName;
}
public void setInputName(String inputName) {
this.inputName = inputName;
}
// rest of class
}
Number the lines
public void numberLines() throws FileNotFoundException {
FileReader reader = new FileReader(inputName);
Scanner in = new Scanner(reader);
PrintWriter out = new PrintWriter(outputName);
int lineNumber = 1;
while (in.hasNextLine()) {
String line = in.nextLine();
out.println("/* " + lineNumber + " */ " + line);
lineNumber++;
}
out.close();
}
FileReader line “opens” the file
What if files is not there? EXCEPTION!
For now, we “acknowledge” with a throws clause
Option 1: hardcode file names

In main
LineNumberer lines1 = new LineNumberer();
lines1.setInputName("srcCode.txt");
lines1.setOutputName("srcCode1.out");
lines1.numberLines();
This is clearly not the most flexible option! Use sparingly!
Option 2: prompt for names
public void promptForInputFile() {
Scanner scan = new Scanner(System.in);
System.out.print("Enter the input file name: ");
inputName = scan.next();
}

In main
LineNumberer lines2 = new LineNumberer();
lines2.setOutputName("srcCode2.out");
lines2.promptForInputFile();
lines2.numberLines();
Option 3: File Chooser
•
Can use javax.swing.JFileChooser.
public void chooseFileName() {
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(null) ==
JFileChooser.APPROVE_OPTION) {
// static int
File selectedFile = chooser.getSelectedFile();
inputName = selectedFile.getAbsolutePath();
}
}

In main
LineNumberer lines3 = new LineNumberer();
lines3.setOutputName("srcCode3.out");
lines3.chooseFileName();
lines3.numberLines();
Option 4: Command line

Can accept filenames on the command line. May be
easier to automate (e.g., put in a script)
LineNumberer lines4 = new LineNumberer();
lines4.setOutputName("srcCode4.out");
if (args.length > 0) {
lines4.setInputName(args[0]);
lines4.numberLines();
}
Eclipse New Run Configuration
Select Run icon
Press New Configuration Icon (be sure Java application is selected
Fill in Name,
Project and
Main Class as
needed
Eclipse Arguments

Click on Arguments tag to add Program Arguments
What did we just learn?




How to open a file
How to read from a file using Scanner
Four ways to specify file names
The throws clause
File Total



Program to calculate the sum of the values in a file
Handles situation if file not found
Handles situation if non-numeric value found
FileTotal - Program Structure
public class FileTotal {
private int sum;
private String inFile;
public FileTotal(String inFile) {
this.inFile = inFile;
}
public void displaySum() {
System.out.println("Sum is " + sum);
}
public static void main(String[] args) {
FileTotal ft = new FileTotal("numbers.txt");
ft.sumFileValues();
ft.displaySum();
}
}
The fun part
public void sumFileValues() {
FileReader reader = null;
Scanner in = null;
String strNum = null;
try {
while (in.hasNext()) {
strNum = in.next();
try {
int num =
reader = new
FileReader(inFile);
in = new Scanner(reader);
} catch
(FileNotFoundException e) {
System.out.println
(e.getLocalizedMessage());
}
Integer.parseInt(strNum);
sum += num;
}
} catch
(NumberFormatException e)
{
System.out.println("Error,
non-numeric value " +
strNum);
} }
What if we wanted to print error but continue summing?
Quick Exercise – 5 minutes!
Goal: Try basic error handling
 Create a Java Project called ExceptionsDemo
 Create a class named ReadAFile
 Create a method named loadFile
 Write lines of code in loadFile to:





open a file named “numbers.txt”
read the first number
display on console
put the code in a try/catch block
display an error if file not found
NOTE: names are just suggestions, this will not be turned in
Software Engineering Quality Tip

Throw Early, Catch Late. Better to throw an exception
than come up with an imperfect fix. What should
program do if a file is not found? Is it always an error?

Do not squelch exceptions!
try
{
FileReader reader = new FileReader(filename);
…
} catch (Exception e) {} // So there!
Checked and Unchecked
•
•
•
Checked exceptions – can’t ignore, compiler requires that you
handle or propagate
Unchecked exceptions – can be ignored. Generally subclass of
RuntimeException, like NumberFormatException or
NullPointerException. Too expensive to check all of these,
often due to programmer error (checked exceptions often
user error, like InputMismatchException)
If you aren’t going to handle a checked exception, put throws
clause on function header:
public void read(String filename) throws
FileNotFoundException
{ . . .}
Quick Exercise – 5 minutes
Goal: Understand checked/unchecked exceptions
 Remove the try/catch from your previous exercise. What
error message do you see?
 Put a “throws clause” on your loadFile method. What
error do you see?
 Put a “throws clause” on main.
 Run the program. What happens?
 Put the lines: Point p; system.out.println(p.getX()); in main.
Does the compiler show an error? Would there be an
error when you run the program?
Exception Hierarchy
Throwable
Error
IOException
ClassNot
FoundException
Exception
CloneNot
Supported
Exception
RuntimeException
ArithmeticException
EOFException
ClassCastException
FileNotFoundException
IllegalStateException
MalformedURLException
NumberFormatException
IndexOutOfBoundsException
UnknownHostException
ArrayIndexOutOfBoundsException
NoSuchElementException
NullPointerException
Finally Clause
•
Sometimes cleanup is needed even after an exception
occurs
PrintWriter out = new PrintWriter(filename);
try {
writeData(out);
}
finally
{
out.close(); // always executed, including after
}
// exception is handled in a catch
Throwing an Exception
public class ThrowException {
public static void main(String[] args)
throws Exception {
public void getInput() throws Exception {
ThrowException demo = new
ThrowException();
Scanner scan = new Scanner(System.in);
System.out.print("Enter a number from 1 - 100: ");
try {
demo.getInput();
int num = scan.nextInt();
} catch (Exception e) {
if (num < 1 || num > 100)
System.out.println(e);
throw new Exception("The value " +
System.out.println(e.getMessage());
num + " is not between 1 and
100!");
}
}
}
}
Is this a good use of exceptions? Probably not… if you can handle
immediately with if/else logic, that’s better!
But this example at least shows the mechanics of throwing an exception.
Restricted File Total


Calculates the sum of values in file
Values must be greater than 0
NOTE: In reality, we might handle this with a simple if/else
But this is a simple exercise to see how custom exceptions work
Exception Best Practices are discussed in Programming Languages
RestrictedFileTotal - Program Structure
public class RestrictedFileTotal {
private int sum;
private String inFile;
public RestrictedFileTotal(String inFile) {
this.inFile = inFile;
}
public void displaySum() {
System.out.println("Sum is " + sum);
}
}
Designing your own Exception
public class NegativeNumberException extends Exception {
private int number;
public NegativeNumberException() {}
public NegativeNumberException(String message) {
super(message);
}
public NegativeNumberException(int number) {
super("Error: value can't be < 0, input = " + number);
this.number = number;
}
public String toString() {
return "Error: negative number encountered " + number;
}
Could extend RuntimeException, if programmer can prevent
}
Do we really need number? Probably not! Again, this is just to
show the mechanics in a simple example.
Throw your Exception
public void sumFileValues() throws
catch (FileNotFoundException e) {
System.out.println(e.getLocalizedMessage());
NegativeNumberException {
FileReader reader = null;
} catch (NumberFormatException e) {
System.out.println("Error, non-numeric value “
Scanner in = null;
+ strNum);
String strNum = null;
}
try {
reader = new FileReader(inFile);
}
in = new Scanner(reader);
while (in.hasNext()) {
strNum = in.next();
int num = Integer.parseInt(strNum);
if (num < 0)
throw new NegativeNumberException(num);
sum += num; }
}
Catch your Exception
public static void main(String[] args) {
RestrictedFileTotal ft = new
RestrictedFileTotal("numbers.txt");
try {
ft.sumFileValues();
} catch (NegativeNumberException e) {
System.out.println(e);
}
ft.displaySum();
}
Download