Topic: 一段代码完成经过!(ZT)

  Print this page

1.一段代码完成经过!(ZT) Copy to clipboard
Posted by: jameszhang
Posted on: 2003-11-05 09:20

一段非常好的异常处理,完整的!代码来自Core Java Technologies Tech Tips, November 4, 2003

HANDLING EXCEPTIONS
Often programmers who are new to the Java programming language see exceptions as little more than annoyances to be ignored and dismissed. The advantage of handling exceptions is that you are forced to think about what could go wrong with your code at runtime. This Tech Tip will present techniques for handling exceptions. Here you'll learn why it's best to deal with exceptions close to their source and as specifically as possible. The goal of exception handling is to help users better run your software.

Consider what happens when a user tries to read from a file. The user specifies the name of the file as a command line parameter. In response, a File object is created from the name of the file (a String). A FileReader object is created to read the contents of the File. A BufferedReader is then chained to facilitate the reading of the text contents of the File.

What is not being taken into account are all of the things that could go wrong. For example, the user might not specify a file name when the program is run. Or the user might specify a file name, but no file exists that corresponds to that name. Taking account of things that could go wrong is what exception handling is about.

A good way to see the value of handling exceptions is to see what happens when you do not take any particular exception handling actions. Let's start with the following program, BadFileAccess:

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;

public class BadFileAccess {

// do NOT code like this

public static void main(String[] args) {
String fileName = args[0];
File aFile = new File(fileName);
FileReader fileReader = new FileReader(aFile);
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
}
}

BadFileAccess does not compile. If you try to compile the program, the compiler complains that there are two unreported exceptions: a java.io.FileNotFoundException and a java.io.IOException. FileNotFoundException extends IOException, which in turn, extends java.io.Exception. Instead of taking some specific actions to handle the exceptions, you might simply treat the exceptions generically, that is, by taking advantage of the exceptions hierarchy. In other words, you might consider both exceptions as instances of the Exception class like this:

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;

public class BadFileAccess {

// do NOT code like this

public static void main(String[] args) {
String fileName = args[0];
File aFile = new File(fileName);
try {
FileReader fileReader = new FileReader(aFile);
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
} catch (Exception e) {
// especially avoid coding like this
}
}
}

Compile the code. You should see that it now compiles. What you don't see yet is that it contains many runtime errors. To see one of these errors, run the code without specifying a parameter, like this:

java BadFileAccess

When you try this, you should get an ArrayIndexOutOfBoundsException. The exception is thrown by the reference to args[0] in the program. The exception forces the program to quit. This might be what you want to happen if a user tries to run the program without specifying a file name. But seeing ArrayIndexOutOfBoundsException might not help an end user realize that they have to to enter the name of a legitimate file.

Now let's look at a what you could do to handle the exception. One tempting approach is to use the technique described in the January 09, 2001 Tech Tip titled Handling Uncaught Exceptions. Using that technique, you include the line

String fileName = args[0];

in the try block. Here's what the BadFileAccess program looks like with the new line:

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;

public class BadFileAccess {

// do NOT code like this
// this is the WORST version

public static void main(String[] args) {
try{
String fileName = args[0];
File aFile = new File(fileName);
FileReader fileReader = new FileReader(aFile);
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
} catch (Exception e) {
// especially avoid coding like this
}
}
}

Compile and run the code as before. The program compiles, but now there's no indication of the ArrayIndexOutOfBoundsException when you run the program. So this technique is not a good one for alerting the user to the problem. What you need to do here is trap the ArrayIndexOutOfBoundsException before the catch block for the generic Exception, and provide a helpful message to the user. Here's what the BadFileAccess program looks like with the addition of the trapping code and the helpful message:

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;

public class BadFileAccess {

// do NOT code like this

public static void main(String[] args) {

try {
String fileName = args[0];
File aFile = new File(fileName);
FileReader fileReader = new FileReader(aFile);
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("correct usage: " +
"java BadFileAccess <pathToFile>");
} catch (Exception e) {
// especially avoid coding like this
}
}
}

Compile and run the updated program as before. When you run it, you should see the message:

correct usage: java BadFileAccess <pathToFile>

It's easy to imagine a main() method in the program where different Arrays are accessed. In that case, you might not want the same message issued for all ArrayIndexOutOfBoundsExceptions. In general, it's best to handle each exception as close to its cause as possible. To do this, you need to move the line

String fileName = args[0];

and declare and initialize the variable outside of the try block like this:

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;

public class BadFileAccess {

// do NOT code like this

public static void main(String[] args) {
String fileName = null;
try {
fileName = args[0];
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("correct usage: " + "" +
"java BadFileAccess <pathToFile>");
}
try {
File aFile = new File(fileName);
FileReader fileReader = new FileReader(aFile);
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
} catch (Exception e) {
// especially avoid coding like this
}
}
}

Now let's handle the case of a user specifying an invalid file name. Assume in this example that the file named noFile does not exist. Execute the following command:

java BadFileAccess noFile.txt

The good news is that nothing seems to be amiss. When you execute the command, you should not see an error message. Of course, that is exactly the problem. You should get some indication that no file exists with the name noFile.txt. Recall that the FileReader constructor can throw a FileNotFoundException. To handle the invalid file type of exception, add another catch block:

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;

public class BadFileAccess {

// do NOT code like this

public static void main(String[] args) {
String fileName = null;
try {
fileName = args[0];
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("correct usage: " +
"java BadFileAccess <pathToFile>");
}
try {
File aFile = new File(fileName);
FileReader fileReader = new FileReader(aFile);
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
}catch (FileNotFoundException e){
System.out.println(" There is no file at " +
fileName);
} catch (Exception e) {
// especially avoid coding like this
}
}
}

Compile the program and run it, specifying noFile.txt as the file name. You should now see the message:

There is no file at noFile.txt

At this point, you have added code that covers two exceptional cases: running the program without specifying a file name, and running the program specifying an invalid file name. But there's more that you can do to help the user. For example, you can indicate that not specifying a file name or specifying an invalid file name leads to a problem in locating the file. In addition, you can create your own exception depending on the situation. For example, if no file name is specified, you create a FileNotFoundException with an appropriate error message. You are no longer catching an ArrayIndexOutOfBoundsException. You test to see if there is one command line parameter. If there is, you try to open a file at that location. If there is not, you throw a new FileNotFoundException. If no file exists at the path the user specifies, you create a FileNotFoundException with an error message appropriate for that situation.

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;

public class BadFileAccess {

// do NOT code like this

private static String fileName;

public static void main(String[] args) {
try {
FileReader fileReader = new FileReader(
getFile(args));
BufferedReader buffReader =
new BufferedReader(fileReader);
while (true) {
System.out.println(buffReader.readLine());
}
}catch (FileNotFoundException e){
System.out.println(
"Could not locate a file: " +
e.getMessage());
} catch (Exception e) {
// especially avoid coding like this
}
}

private static File getFile(String[] args)
throws FileNotFoundException {
if(args.length == 1){
fileName = args[0];
} else {
throw new FileNotFoundException(
"correct usage: " +
"java BadFileAccess <pathToFile>");
}
File aFile = new File(fileName);
if (aFile.exists()) {
return aFile;
} else {
throw new FileNotFoundException(
"There is no file at " + fileName);
}
}
}

Compile the program and run it without specifying a file name. The program throws a FileNotFoundException, and displays the message:

Could not locate a file:
correct usage: java BadFileAccess <pathToFile>

Run the program with an invalid file name, for example:

java BadFileAccess noFile.txt

The program throws a FileNotFoundException, and displays the message:

Could not locate a file:
There is no file at noFile.txt

You can avoid creating multiple instances of a FileNotFoundException by following the advice of the April 22, 2003 Tech Tip on reusing exceptions. That tip shows how to use a Singleton, setting its properties for each instance of the same exception. Alternatively, you can handle the exception in the getFile() method without rethrowing.

In any case, if you read from an actual text file, the following block causes a problem that you have yet to address.

while (true) {
System.out.println(buffReader.readLine());
}

Here's an example of the problem. Create a plain text file named realFile.txt. Fill it with sample text such as "This is a sample document." Now run your application like this.

java BadFileAccess realFile.txt

You should see output that contains the line "This is a sample document." That line is followed by the word "null" on succeeding lines. The "null" lines continue to fill the output until you halt execution. This continuous result happens because there is nothing in your program to stop reading from the file when it reaches the end.

What can you do to help the user here? The readLine() method from the BufferedReader class can throw an IOException. There is not much users can do if they encounter an IOException at that point, but you can include a message that makes it clear to them what happened. For example, the following program, FileAccess, displays an explanatory message if there is an IOException:

import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.BufferedReader;
import java.io.IOException;

public class FileAccess {

private static String fileName;

public static void main(String[] args) {
FileReader fileReader = null;
try {
fileReader = new FileReader(getFile(args));

} catch (FileNotFoundException e) {
System.out.println(
"Could not locate a file: " +
e.getMessage());
}
readFile(fileReader);
}

private static File getFile(String[] args)
throws FileNotFoundException {
try {
fileName = args[0];
} catch (ArrayIndexOutOfBoundsException e) {
throw new FileNotFoundException(
"correct usage: " +
"java FileAccess <pathToFile>");

}
File aFile = new File(fileName);
if (aFile.exists()) {
return aFile;
} else {
throw new FileNotFoundException(
"There is no file at " + fileName);
}
}

private static void readFile(
FileReader fileReader) {
BufferedReader buffReader =
new BufferedReader(fileReader);
String temp = "";
try {
System.out.println(
"== Beginning of the file: " +
fileName + " ==");
while ((temp = buffReader.readLine()) != null) {
System.out.println(temp);
}
} catch (IOException e) {
System.out.println("There was a problem reading:"
+ fileName);
}
System.out.println("== End of the file: " +
fileName + " ==");
}
}

If you run the application like this:

java BadFileAccess realFile.txt

You should see this:

== Beginning of the file: realFile.txt ==
This a sample document.
== End of the file: realFile.txt ==

2.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: taogang
Posted on: 2003-11-05 11:03

有最好的写法么?还要看应用环境吧(个人意见,Smile)

3.Re:一段代码完成经过! [Re: taogang] Copy to clipboard
Posted by: jameszhang
Posted on: 2003-11-05 11:34

taogang wrote:
有最好的写法么?还要看应用环境吧(个人意见,Smile)

oO! 你是否仔细看过代码?Smile

4.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: heaven
Posted on: 2003-11-05 12:31

最后一种也还可以改的,一串static method,就像c函数.

5.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: altonpeng
Posted on: 2003-11-05 13:15

最后一种不错

6.Re:一段代码完成经过! [Re: taogang] Copy to clipboard
Posted by: alinew
Posted on: 2003-11-05 14:39

到是挺会改标题的..hehe
代码来自Core Java Technologies Tech Tips, November 4, 2003 (Handling Exceptions, TimeZone Class)的Handling Exceptions部分

7.Re:一段代码完成经过! [Re: alinew] Copy to clipboard
Posted by: jameszhang
Posted on: 2003-11-05 20:25

alinew wrote:
到是挺会改标题的..hehe
代码来自Core Java Technologies Tech Tips, November 4, 2003 (Handling Exceptions, TimeZone Class)的Handling Exceptions部分

被你看穿了,呵呵,怎么会这多兄弟都没订购呢? 我觉得那里的代码都很经典,呵呵

8.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: bjwz
Posted on: 2003-11-07 10:35

没太看明白

9.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: wenbl
Posted on: 2003-11-09 13:16

I registered ,but i always have no time to read and study it, so regret!

10.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: vicious
Posted on: 2003-11-10 12:15

有什么用啊?

11.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: yb79528
Posted on: 2003-11-10 16:07

学习精益求精的探索精神,看了代码,对文件操作有了更多的认识了

12.Re:一段代码完成经过! [Re: yb79528] Copy to clipboard
Posted by: nothing
Posted on: 2003-11-10 16:18

see,see;
支持一下.

13.Re:一段代码完成经过! [Re: jameszhang] Copy to clipboard
Posted by: nova
Posted on: 2003-11-10 16:30

我想这个代码主要是代表了二方面

1、例外处理
2、OO

14.Re:一段代码完成经过! [Re: yb79528] Copy to clipboard
Posted by: gunrose
Posted on: 2003-11-12 07:45

好像和原来不一样了,为什么不显示成code模式?

15.Re:一段代码完成经过!(ZT) [Re: jameszhang] Copy to clipboard
Posted by: TopCool
Posted on: 2003-11-12 09:49

我也想订阅,怎么定??

help me

16.Re:一段代码完成经过!(ZT) [Re: TopCool] Copy to clipboard
Posted by: jameszhang
Posted on: 2003-11-12 09:57

TopCool wrote:
我也想订阅,怎么定??

help me

http://developer.java.sun.com/developer/JDCTechTips/

17.Re:一段代码完成经过!(ZT) [Re: jameszhang] Copy to clipboard
Posted by: helloworld
Posted on: 2003-11-12 10:17

Thank you for subscribing to Sun Developer Network publications.
You have been added to the following subscriptions:
Enterprise Java Technology (J2EE, Sun ONE)
Core Java Technologies Tech Tips
Core Java Technologies Newsletter
Enterprise Java Technologies Tech Tips
Enterprise Java Technologies Newsletter
Core Java Technology (J2SE)

You will soon receive an email to confirm your subscription request. Please follow the instructions in that email to activate your subscription.

18.Re:一段代码完成经过!(ZT) [Re: jameszhang] Copy to clipboard
Posted by: hailwind
Posted on: 2003-11-14 12:07

好。


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923