生成一个文本文件 pw.txt,用于记录多行日志信息。pw.txt 文件的内容如图-1所示:
图-1
实现此案例需要按照如下步骤进行。
步骤一:新建TestPrintWriter类,添加测试方法testPrintWriter方法
首先,新建名为TestPrintWriter的类,并在类中添加单元测试方法 testPrintWriter。代码如下所示:
import java.io.PrintWriter; import org.junit.Test; /** * 测试缓冲字符输出流 * */ public class TestPrintWriter { /** * 测试缓冲字符输出流 * @throws Exception */ @Test public void testPrintWriter()throws Exception{ } }
步骤二:将多行文本写入文件
PrintWriter是带有行刷新的缓冲字符输出流,它提供了丰富的重载print与println方法。其中,println方法在于输出目标数据后自动输出一个系统支持的换行符。
为向文本文件中写入多行日志信息,首先需要创建一个 PrintWriter类的对象,用于写入文件,然后调用 println 方法写入文本,最后关闭PrintWriter对象。代码如下所示:
import java.io.PrintWriter; import org.junit.Test; /** * 测试缓冲字符输出流 * */ public class TestPrintWriter { /** * 测试缓冲字符输出流 * @throws Exception */ @Test public void testPrintWriter()throws Exception{ #cold_bold PrintWriter pw = new PrintWriter("pw.txt"); #cold_bold pw.println("大家好!"); #cold_bold pw.println("hello!"); #cold_bold pw.println("bye!"); #cold_bold pw.close(); } }
步骤三:测试
运行testPrintWriter方法,将在当前工程下生成一个名为 pw.txt 的文件,打开该文件,文件中的内容和图-1相同。
本案例的完整代码如下所示:
import java.io.PrintWriter; import org.junit.Test; /** * 测试缓冲字符输出流 * */ public class TestPrintWriter { /** * 测试缓冲字符输出流 * @throws Exception */ @Test public void testPrintWriter()throws Exception{ PrintWriter pw = new PrintWriter("pw.txt"); pw.println("大家好!"); pw.println("hello!"); pw.println("bye!"); pw.close(); } }
读取上一个案例中所创建的文本文件中的内容,并逐行打印显示,效果如图-2所示:
图-2
首先需要创建文件字节输入流FileInputStream,用于读入文件,代码如:
FileInputStream fis = new FileInputStream("pw.txt");
然后使用所创建的文件字节输入流对象作为参数,构建InputStreamReader类的对象,用于将字节流变为字符流,代码如:
InputStreamReader isr = new InputStreamReader(fis);
再使用所创建的字符输入流对象作为参数,创建BufferedReader类的对象,用于逐行读取文本文件的所有行,代码如:
BufferedReader br = new BufferedReader(isr);
随后,调用 BufferedReader的 readLine方法读取一行文本。需要注意的是,如果因已到达流末尾而没有可读的内容,readLine 则返回null。因此,需要构建 while 循环来逐一读取文件中的每行文本,代码如:
String line = null; while((line = br.readLine())!=null){ }
实现此案例需要按照如下步骤进行。
步骤一:新建TestBufferedReader类,添加测试方法testBufferedReader方法
首先,新建名为TestBufferedReader的类,并在类中添加单元测试方法 testBufferedReader。代码如下所示:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import org.junit.Test; /** * 测试缓冲字符输入流 * */ public class TestBufferedReader { /** * 使用缓冲字符输入流读取文本文件 * @throws Exception */ @Test public void testBufferedReader()throws Exception{ } }
步骤二:读取文本文件的所有行
创建BufferedReader类的对象,并调用该对象的 readLine 方法逐一读取文件中的每行文本并打印显示。注意:使用完毕后,需要关闭BufferedReader对象。
代码如下所示:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import org.junit.Test; /** * 测试缓冲字符输入流 * */ public class TestBufferedReader { /** * 使用缓冲字符输入流读取文本文件 * @throws Exception */ @Test public void testBufferedReader()throws Exception{ #cold_bold FileInputStream fis = new FileInputStream("pw.txt"); #cold_bold InputStreamReader isr = new InputStreamReader(fis); #cold_bold BufferedReader br = new BufferedReader(isr); #cold_bold #cold_bold String line = null; #cold_bold while((line = br.readLine())!=null){ #cold_bold System.out.println(line); #cold_bold } #cold_bold #cold_bold br.close(); } }
步骤三:测试
运行testBufferedReader方法,将逐行打印显示文件中的内容。
本案例的完整代码如下所示:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import org.junit.Test; /** * 测试缓冲字符输入流 * */ public class TestBufferedReader { /** * 使用缓冲字符输入流读取文本文件 * @throws Exception */ @Test public void testBufferedReader()throws Exception{ FileInputStream fis = new FileInputStream("pw.txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String line = null; while((line = br.readLine())!=null){ System.out.println(line); } br.close(); } }
创建工具类 FileUtils,为其定义文件复制方法,实现文件复制功能,并添加异常处理机制。
前面的案例中,已经描述过文件复制功能的实现,此案例需要为其添加异常处理机制,用来处理复制过程中的各种异常情况,如需要复制的文件不存在等。
需要使用 try 语句捕获代码可能会产生的异常对象,并使用 catch语句对异常做相应的处理。每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常,代码如下所示:
FileInputStream fis = null; FileOutputStream fos = null; try { //... 代码 } catch (FileNotFoundException e) { System.err.println("文件没有找到"); e.printStackTrace(); } catch (IOException e) { System.err.println("读写异常"); e.printStackTrace(); }
上述代码中,可以捕获处理FileNotFoundException异常,以及 IOException。
finally语句为异常处理提供一个统一的出口,通常在finally语句中可以进行资源的消除工作,如关闭打开的文件、删除临时文件等。代码如下所示:
FileInputStream fis = null; FileOutputStream fos = null; try { //... 代码 } catch (FileNotFoundException e) { //... 处理异常的代码 } catch (IOException e) { //...处理异常的代码 } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
实现此案例需要按照如下步骤进行。
步骤一:新建FileUtils类,添加测试方法testCopy方法
首先,新建名为FileUtils的类,并在类中添加单元测试方法 testCopy。代码如下所示:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class FileUtils { /** * 对复制文件的代码添加异常捕获机制 */ @Test public void testCopy() { } }
步骤二:实现文件复制功能
为方法testCopy添加代码,实现文件复制功能,代码如下所示:
public void testCopy() { #cold_bold FileInputStream fis = null; #cold_bold FileOutputStream fos = null; #cold_bold fis = new FileInputStream("fos.dat"); #cold_bold fos = new FileOutputStream("fos_copy4.dat"); #cold_bold int d = -1; #cold_bold while ((d = fis.read()) != -1) { #cold_bold fos.write(d); #cold_bold } #cold_bold System.out.println("复制完毕"); }
步骤三:捕获并处理异常
为上一步骤中的代码添加 try/catch 语句,以实现异常的处理。
先处理 FileNotFoundException 异常,然后处理 IOException 异常,代码如下所示:
public void testCopy() { FileInputStream fis = null; FileOutputStream fos = null; #cold_bold try { fis = new FileInputStream("fos.dat"); fos = new FileOutputStream("fos_copy4.dat"); int d = -1; while ((d = fis.read()) != -1) { fos.write(d); } System.out.println("复制完毕"); #cold_bold } catch (FileNotFoundException e) { #cold_bold System.err.println("文件没有找到"); #cold_bold e.printStackTrace(); #cold_bold } catch (IOException e) { #cold_bold System.err.println("读写异常"); #cold_bold e.printStackTrace(); #cold_bold } }
步骤四:资源清理
使用 finally 语句释放相关资源,代码如下所示:
public void testCopy() { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("fos.dat"); fos = new FileOutputStream("fos_copy4.dat"); int d = -1; while ((d = fis.read()) != -1) { fos.write(d); } System.out.println("复制完毕"); } catch (FileNotFoundException e) { System.err.println("文件没有找到"); e.printStackTrace(); } catch (IOException e) { System.err.println("读写异常"); e.printStackTrace(); #cold_bold } finally { #cold_bold if (fis != null) { #cold_bold try { #cold_bold fis.close(); #cold_bold } catch (IOException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold if (fos != null) { #cold_bold try { #cold_bold fos.close(); #cold_bold } catch (IOException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold } }
步骤五:测试
运行testCopy方法,如果当前工程目录下没有文件fos.dat,则将产生FileNotFoundException 异常。
本案例中,类FileUtils的完整代码如下所示:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class FileUtils { /** * 对复制文件的代码添加异常捕获机制 */ @Test public void testCopy() { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("fos.dat"); fos = new FileOutputStream("fos_copy4.dat"); int d = -1; while ((d = fis.read()) != -1) { fos.write(d); } System.out.println("复制完毕"); } catch (FileNotFoundException e) { System.err.println("文件没有找到"); e.printStackTrace(); } catch (IOException e) { System.err.println("读写异常"); e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
写代码,制造常见的RuntimeException异常,详细要求如下:
1)制造空指针异常NullPointerException;
2)制造数组越界异常ArrayIndexOutOfBoundsException;
3)制造数学异常ArithmeticException;
4)制造强制类型转换异常ClassCastException;
5)制造数值格式化异常NumberFormatException
实现此案例需要按照如下步骤进行。
步骤一:新建类
新建类TestRuntimeException,代码如下所示:
/** * 测试常见的运行时异常 */ public class TestRuntimeException { }
步骤二:制造空指针异常
当一个引用的值为null的时候,如果通过引用访问对象成员变量或者调用方法,此时,会产生NullPointerException。在此,首先创建测试方法testNullPointerException;然后,将String类的引用str赋值为null;最后,调用String类的length方法即会发生空指针异常,代码如下所示:
import org.junit.Test; /** * 测试常见的运行时异常 */ public class TestRuntimeException { #cold_bold /** #cold_bold * 测试空指针异常 #cold_bold */ #cold_bold @Test #cold_bold public void testNullPointerException(){ #cold_bold String str = null; #cold_bold //会引发空指针异常 #cold_bold System.out.println(str.length()); #cold_bold } }
运行testNullPointerException方法,在JUnit视图下会显示抛出了空指针异常,如图-3所示。
图- 3
步骤三:制造数组下标越界异常
如果使用为负或大于等于数组大小的索引来访问数组时抛出的异常。在此,首先创建测试方法testArrayIndexOutOfBoundsException;然后,使用String类的getBytes方法返回字符串“hello”对应的字符数组;最后,输出该字符数组中索引为字符数组长度的字符,此操作即会发生数组下标越界异常,代码如下所示:
import org.junit.Test; /** * 测试常见的运行时异常 */ public class TestRuntimeException { /** * 测试空指针异常 */ @Test public void testNullPointerException(){ //...(代码略) } #cold_bold /** #cold_bold * 测试数组下标越界异常 #cold_bold */ #cold_bold @Test #cold_bold public void testArrayIndexOutOfBoundsException(){ #cold_bold byte[] bytes = "hello".getBytes(); #cold_bold //会引发数组下标越界异常 #cold_bold System.out.println(bytes[bytes.length]); #cold_bold } }
运行testArrayIndexOutOfBoundsException方法,在JUnit视图下会显示数组下标越界异常,如图-4所示。
图- 4
步骤四:制造强制类型转换异常
当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此异常。在此,首先创建测试方法testArithmeticException;然后,输出“5除以0”即会发生数学异常,代码如下所示:
import org.junit.Test; /** * 测试常见的运行时异常 */ public class TestRuntimeException { /** * 测试空指针异常 */ @Test public void testNullPointerException(){ //...(代码略) } /** * 测试数组下标越界异常 */ @Test public void testArrayIndexOutOfBoundsException(){ //...(代码略) } #cold_bold /** #cold_bold * 测试数学异常 #cold_bold */ #cold_bold @Test #cold_bold public void testArithmeticException(){ #cold_bold //会引发数学异常 #cold_bold System.out.println(5/0); #cold_bold } }
运行testArithmeticException方法,在JUnit视图下会显示抛出了数学异常,如图-5所示。
图- 5
步骤五:制造强制类型转换异常
当试图将对象强制转换为不是实例的子类时,抛出该异常。在此,首先创建测试方法testClassCastException;然后,创建一个Object类的引用obj,赋值为字符串“hello”;最后将对象obj强制转换为Integer类的对象即会发生强制类型转换异常,代码如下所示:
import org.junit.Test; /** * 测试常见的运行时异常 */ public class TestRuntimeException { /** * 测试空指针异常 */ @Test public void testNullPointerException(){ //...(代码略) } /** * 测试数组下标越界异常 */ @Test public void testArrayIndexOutOfBoundsException(){ //...(代码略) } /** * 测试数学异常 */ @Test public void testArithmeticException(){ //...(代码略) } #cold_bold /** #cold_bold * 测试强制类型转换异常 #cold_bold */ #cold_bold @Test #cold_bold public void testClassCastException(){ #cold_bold Object obj = "hello"; #cold_bold //会引发强制类型转换异常 #cold_bold Integer i = (Integer)obj; #cold_bold } }
运行testClassCastException方法,在JUnit视图下会显示抛出了类型转换异常,如图-6所示。
图-6
步骤六:制造NumberFormat异常
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。在此,首先创建测试方法testNumberFormatException;然后,使用Integer类的parseInt方法将字符串“a”转换为数值即会发生NumberFormat异常,代码如下所示:
import org.junit.Test; /** * 测试常见的运行时异常 */ public class TestRuntimeException { /** * 测试空指针异常 */ @Test public void testNullPointerException(){ //...(代码略) } /** * 测试数组下标越界异常 */ @Test public void testArrayIndexOutOfBoundsException(){ //...(代码略) } /** * 测试数学异常 */ @Test public void testArithmeticException(){ //...(代码略) } /** * 测试强制类型转换异常 */ @Test public void testClassCastException(){ //...(代码略) } #cold_bold /** #cold_bold * 测试NumberFormat异常 #cold_bold */ #cold_bold @Test #cold_bold public void testNumberFormatException(){ #cold_bold //会引发NumberFormat异常 #cold_bold int num = Integer.parseInt("a"); #cold_bold } }
运行testNumberFormatException方法,在JUnit视图下会显示抛出了NumberFormat异常,如图-7所示。
图-7
本案例中,类TestRuntimeException的完整代码如下所示:
import org.junit.Test; /** * 测试常见的运行时异常 */ public class TestRuntimeException { /** * 测试空指针异常 */ @Test public void testNullPointerException(){ String str = null; //会引发空指针异常 System.out.println(str.length()); } /** * 测试数组下标越界异常 */ @Test public void testArrayIndexOutOfBoundsException(){ byte[] bytes = "".getBytes(); //会引发数组下标越界异常 System.out.println(bytes[bytes.length]); } /** * 测试数学异常 */ @Test public void testArithmeticException(){ //会引发数学异常 System.out.println(5/0); } /** * 测试强制类型转换异常 */ @Test public void testClassCastException(){ Object obj = "hello"; //会引发强制类型转换异常 Integer i = (Integer)obj; } /** * 测试NumberFormat异常 */ @Test public void testNumberFormatException(){ //会引发NumberFormat异常 int num = Integer.parseInt("a"); } }
在上一案例的基础上,在工具类 FileUtils中再次定义文件复制方法,实现文件复制功能,并添加自定义异常处理。
实现和使用自定义异常的过程如下:
1)首先,新建自定义异常类CopyException,该类继承自Exception;然后在该类中添加以下四个构造方法,这四个构造方法的实现,都为使用super调用父类对应参数的构造方法即可。以下是自定义异常一般的实现方式,代码如下:
public class CopyException extends Exception{ public CopyException() { super(); } public CopyException(String message, Throwable cause) { super(message, cause); } public CopyException(String message) { super(message); } public CopyException(Throwable cause) { super(cause); } }
2)为了屏蔽底层的IOException,在实现文件复制的异常处理时,抛出自定义异常CopyException,即在catch块内使用throw关键字抛出自定义异常CopyException的实例,代码如下:
try { //实现文件复制 } catch (FileNotFoundException e) { //抛出自定义异常 throw new CopyException("文件没有找到",e); } catch (IOException e) { //抛出自定义异常 throw new CopyException("读写异常",e); }
3)在实现复制的方法声明处使用throws关键字声明该方法会抛出自定义异常CopyException,代码如下:
public void testCopy1()throws CopyException{... ...}
实现此案例需要按照如下步骤进行。
步骤一:新建自定义异常CopyException
首先,新建自定义异常类CopyException,该类继承自Exception;然后在该类中添加以下四个构造方法,这四个构造方法的实现都为使用super调用父类对应参数的构造方法,代码如下所示:
/** * 自定义异常 */ public class CopyException extends Exception{ public CopyException() { super(); } public CopyException(String message, Throwable cause) { super(message, cause); } public CopyException(String message) { super(message); } public CopyException(Throwable cause) { super(cause); } }
步骤二:添加测试方法
在类FileUtils中添加测试方法testCopy1,在该方法中实现文件复制功能,代码如下所示:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class FileUtils { /** * 对复制文件的代码添加异常捕获机制 */ #cold_bold @Test #cold_bold public void testCopy1()throws CopyException{ #cold_bold FileInputStream fis = null; #cold_bold FileOutputStream fos = null; #cold_bold fis = new FileInputStream("fos.dat"); #cold_bold fos = new FileOutputStream("fos_copy4.dat"); #cold_bold int d = -1; #cold_bold while ((d = fis.read()) != -1) { #cold_bold fos.write(d); #cold_bold } #cold_bold System.out.println("复制完毕"); #cold_bold } }
步骤三:捕获并处理异常
为上一步骤中的代码添加自定义异常处理。首先,在catch块内使用throw关键字抛出自定义异常CopyException的实例,然后,在testCopy1方法声明处使用throws关键字声明该方法会抛出自定义异常CopyException,代码如下所示:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class FileUtils { /** * 对复制文件的代码添加异常捕获机制 */ @Test #cold_bold public void testCopy1()throws CopyException{ FileInputStream fis = null; FileOutputStream fos = null; #cold_bold try { fis = new FileInputStream("fos.dat"); fos = new FileOutputStream("fos_copy4.dat"); int d = -1; while ((d = fis.read()) != -1) { fos.write(d); } System.out.println("复制完毕"); #cold_bold } catch (FileNotFoundException e) { #cold_bold //抛出自定义异常 #cold_bold throw new CopyException("文件没有找到",e); #cold_bold } catch (IOException e) { #cold_bold //抛出自定义异常 #cold_bold throw new CopyException("读写异常",e); #cold_bold } } }
步骤四:资源清理
使用 finally块释放相关资源,及时将流fis、fos关闭,代码如下所示:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class FileUtils { /** * 对复制文件的代码添加异常捕获机制 */ @Test public void testCopy1()throws CopyException{ FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("fos.dat"); fos = new FileOutputStream("fos_copy4.dat"); int d = -1; while ((d = fis.read()) != -1) { fos.write(d); } System.out.println("复制完毕"); } catch (FileNotFoundException e) { //抛出自定义异常 throw new CopyException("文件没有找到",e); } catch (IOException e) { //抛出自定义异常 throw new CopyException("读写异常",e); #cold_bold } finally { #cold_bold if (fis != null) { #cold_bold try { #cold_bold fis.close(); #cold_bold } catch (IOException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold if (fos != null) { #cold_bold try { #cold_bold fos.close(); #cold_bold } catch (IOException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold } } }
步骤五:测试
运行testCopy1方法,如果当前工程目录下没有文件fos.dat,则将抛出CopyException异常,如图-8所示。
图-8
本案例中,类CopyException的完整代码如下所示:
/** * 自定义异常 */ public class CopyException extends Exception{ public CopyException() { super(); } public CopyException(String message, Throwable cause) { super(message, cause); } public CopyException(String message) { super(message); } public CopyException(Throwable cause) { super(cause); } }
类FileUtils的完整代码如下所示:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class FileUtils { //...(之前案例的代码,略) /** * 对复制文件的代码添加异常捕获机制 */ @Test public void testCopy1()throws CopyException{ FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("fos.dat"); fos = new FileOutputStream("fos_copy4.dat"); int d = -1; while ((d = fis.read()) != -1) { fos.write(d); } System.out.println("复制完毕"); } catch (FileNotFoundException e) { //抛出自定义异常 throw new CopyException("文件没有找到",e); } catch (IOException e) { //抛出自定义异常 throw new CopyException("读写异常",e); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }