异常和IO流(上)



一、异常

异常就是程序出现的不正常的情况。

1.异常的体系
Throwable
|--Error严重问题,我们不处理。
|--Exception
|--RuntimeException运行期异常,我们需要修正代码
|--非RuntimeException 编译期异常,必须处理的,否则程序编译不通过

2.异常的处理
1)JVM的默认处理
把异常的名称,原因,位置等信息输出在控制台,但是呢程序不能继续执行了。
2)自己处理
A:try...catch...finally: 自己编写处理代码,后面的程序可以继续执行
B:throws: 把自己处理不了的,在方法上声明,告诉调用者,这里有问题

3.自定义异常
继承自Exception或者RuntimeException,只需要提供无参构造和一个带参构造即可

4.异常的注意点
1)父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于等于父的异常 
2)父的方法没有异常抛出,子的重写方法不能有异常抛出
3)父的方法抛出多个异常,子的重写方法必须比父少或者小
4)编译期异常和运行期异常的区别?
编译期异常 必须要处理的,否则编译不通过
运行期异常 可以不处理,也可以处理
5)throw和throws是的区别
throw:
在方法体中,后面跟的是异常对象名,并且只能是一个
throw抛出的是一个异常对象,说明这里肯定有一个异常产生了
throws:
在方法声明上,后面跟的是异常的类名,可以是多个
throws是声明方法有异常,是一种可能性,这个异常并不一定会产生

5.finally关键字
1)finally用于释放资源,它的代码永远会执行。特殊情况:在执行到finally之前jvm退出了
2) final,finally,finalize的区别:
A:final,修饰符(关键字)
如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。
将变量或方法声明为final,可以保证它们在使用中不被改变。
被声明为final的方法只能使用,不能重载。 

B:finally,再异常处理时提供 finally 块来执行任何清除操作。
如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 
C:finalize,方法名。
finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。

3)如果在catch里面有return,finally还仍然执行,并且是在return中间执行的
首先return时把要return的值先处理好,然后再执行finally里的代码,
执行后再将缓存好的要return的值返回


二、File

IO流操作中大部分都是对文件的操作,所以Java就提供了File类供我们来操作文件

1.构造方法
1)File file = new File("e:\\demo\\a.txt"); 根据一个路径得到File对象
2)File file = new File("e:\\demo","a.txt"); 根据一个目录和一个子文件/目录得到File对象
3)File file3 = new File("e:\\demo"); 根据一个目录得到File对象(文件夹)
4) File file = new File(file,"a.txt");  根据一个父File对象和一个子文件/目录得到File对象

2.File类的功能
1)创建功能:
public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来

2)删除功能: public boolean delete()

3)重命名功能:public boolean renameTo(File dest)
如果路径名相同,就是改名。
如果路径名不同,就是改名并剪切。

4)判断功能:
public boolean isDirectory():判断是否是目录
public boolean isFile():判断是否是文件
public boolean exists():判断是否存在
public boolean canRead():判断是否可读
public boolean canWrite():判断是否可写
public boolean isHidden():判断是否隐藏

5)获取功能:
public String getAbsolutePath():获取绝对路径
public String getPath():获取相对路径
public String getName():获取名称
public long length():获取长度。字节数
public long lastModified():获取最后一次的修改时间,毫秒值


6)高级获取功能:
public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组

7)过滤器功能:
public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)


3.案例:
输出指定目录下指定后缀名的文件名称
import java.io.File;
import java.io.FilenameFilter;

/*
 * 判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
 * A:先获取所有的,然后遍历的时候,依次判断,如果满足条件就输出。
 * B:获取的时候就已经是满足条件的了,然后输出即可。
 * 
 * 要想实现这个效果,就必须学习一个接口:文件名称过滤器
 * public String[] list(FilenameFilter filter)
 * public File[] listFiles(FilenameFilter filter)
 */
public class FileDemo2 {
	public static void main(String[] args) {
		// 封装e判断目录
		File file = new File("e:\\");

		// 获取该目录下所有文件或者文件夹的String数组
		// public String[] list(FilenameFilter filter)
		String[] strArray = file.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				// return false;
				// return true;
				// 通过这个测试,我们就知道了,到底把这个文件或者文件夹的名称加不加到数组中,取决于这里的返回值是true还是false
				// 所以,这个的true或者false应该是我们通过某种判断得到的
				// System.out.println(dir + "---" + name);
				// File file = new File(dir, name);
				// // System.out.println(file);
				// boolean flag = file.isFile();
				// boolean flag2 = name.endsWith(".jpg");
				// return flag && flag2;
				return new File(dir, name).isFile() && name.endsWith(".jpg");
			}
		});

		// 遍历
		for (String s : strArray) {
			System.out.println(s);
		}
	}
}



三、递归


方法定义中调用方法本身的现象叫做递归


1.递归的注意事项;
1)要有出口,否则就是死递归
2)次数不能过多,否则内存溢出
3)构造方法不能递归使用

2.递归的案例:

递归输出指定目录下所有指定后缀名的文件绝对路径

import java.io.File;

/*
 * 需求:请大家把E:\JavaSE目录下所有的java结尾的文件的绝对路径给输出在控制台。
 * 
 * 分析:
 * 		A:封装目录
 * 		B:获取该目录下所有的文件或者文件夹的File数组
 * 		C:遍历该File数组,得到每一个File对象
 * 		D:判断该File对象是否是文件夹
 * 			是:回到B
 * 			否:继续判断是否以.java结尾
 * 				是:就输出该文件的绝对路径
 * 				否:不搭理它
 */
public class FilePathDemo {
	public static void main(String[] args) {
		// 封装目录
		File srcFolder = new File("E:\\JavaSE");

		// 递归功能实现
		getAllJavaFilePaths(srcFolder);
	}

	private static void getAllJavaFilePaths(File srcFolder) {
		// 获取该目录下所有的文件或者文件夹的File数组
		File[] fileArray = srcFolder.listFiles();

		// 遍历该File数组,得到每一个File对象
		for (File file : fileArray) {
			// 判断该File对象是否是文件夹
			if (file.isDirectory()) {
				getAllJavaFilePaths(file);
			} else {
				// 继续判断是否以.java结尾
				if (file.getName().endsWith(".java")) {
					// 就输出该文件的绝对路径
					System.out.println(file.getAbsolutePath());
				}
			}
		}
	}
}


四、IO流概述与字节流


IO用于在设备间进行数据传输的操作 


1.分类:

1)流向

输入流 读取数据

输出流 写出数据

2)数据类型

字节流

字节输入流

字节输出流

字符流

字符输入流

字符输出流

3)注意:

A:如果没有明确说明按照什么分,默认按照数据类型分。

B:除非文件用记事本打开能够读懂,才采用字符流,否则建议使用字节流。


2.FileOutputStream写出数据

1)构造方法:

FileOutputStream(File file) 

FileOutputStream(String name)

FileOutputStream(String name, boolean append);


1)操作步骤

A:创建字节输出流对象

B:调用write()方法

C:释放资源


2)代码体现:

FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();


3)注意

A:创建字节输出流对象所做的事情

a:调用系统功能去创建文件

b:创建fos对象

b:把fos对象指向这个文件

B:close()的作用:释放资源

a:让流对象变成垃圾,这样就可以被垃圾回收器回收了

b:通知系统去释放跟该文件相关的资源

C:实现数据的换行方式:

写入换行符号:

windows:\r\n

linux:\n

Mac:\r

D:实现数据的追加写入的方式:用构造方法带第二个参数是true的情况即可


4)案例

public class FileOutputStreamDemo3 {
	public static void main(String[] args) throws IOException {
		// 创建字节输出流对象
		// FileOutputStream fos = new FileOutputStream("fos3.txt");
		// 创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处
		FileOutputStream fos = new FileOutputStream("fos3.txt", true);

		// 写数据
		for (int x = 0; x < 10; x++) {
			fos.write(("hello" + x).getBytes());
			fos.write("\r\n".getBytes());
		}

		// 释放资源
		fos.close();
	}
}


3.FileInputStream读取数据

1)构造方法:

FileInputStream(String name)


2)操作步骤

A:创建字节输入流对象

B:调用read()方法

C:释放资源


3)代码体现:

		FileInputStream fis = new FileInputStream("fos.txt");

		// 方式1
		int by = 0;
		while ((by = fis.read()) != -1) {
			System.out.print((char) by);
		}

		// 方式2
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = fis.read(bys)) != -1) {
			System.out.print(new String(bys, 0, len));
		}

		fis.close();


4.字节缓冲区流

java开始在设计的时候,考虑到了一次读一个字节速度很慢,就专门提供了带缓冲区的字节类。

这种类被称为:缓冲区类(高效类)

构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了

1)BufferedOutputStream:写数据

构造方法:BufferedInputStream(InputStream in)

2)BufferedInputStream:读数据

构造方法:BufferedOutputStream(OutputStream out)


5.案例


package cn.itcast_06;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 需求:把e:\\test.mp4复制到当前项目目录下的copy.mp4中
 * 
 * 字节流四种方式复制文件:
 * 基本字节流一次读写一个字节:	共耗时:117000毫秒
 * 基本字节流一次读写一个字节数组: 共耗时:150毫秒
 * 高效字节流一次读写一个字节: 共耗时:1100毫秒
 * 高效字节流一次读写一个字节数组: 共耗时:40毫秒
 */
public class CopyMp4Demo {
	public static void main(String[] args) throws IOException {
		long start = System.currentTimeMillis();
		// method1("e:\\test.mp4", "copy1.mp4");
		// method2("e:\\test.mp4", "copy2.mp4");
		// method3("e:\\test.mp4", "copy3.mp4");
		method4("e:\\test.mp4", "copy4.mp4");
		long end = System.currentTimeMillis();
		System.out.println("共耗时:" + (end - start) + "毫秒");
	}

	// 高效字节流一次读写一个字节数组:
	public static void method4(String srcString, String destString)
			throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				srcString));
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(destString));

		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = bis.read(bys)) != -1) {
			bos.write(bys, 0, len);
		}

		bos.close();
		bis.close();
	}

	// 高效字节流一次读写一个字节:
	public static void method3(String srcString, String destString)
			throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				srcString));
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(destString));

		int by = 0;
		while ((by = bis.read()) != -1) {
			bos.write(by);

		}

		bos.close();
		bis.close();
	}

	// 基本字节流一次读写一个字节数组
	public static void method2(String srcString, String destString)
			throws IOException {
		FileInputStream fis = new FileInputStream(srcString);
		FileOutputStream fos = new FileOutputStream(destString);

		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = fis.read(bys)) != -1) {
			fos.write(bys, 0, len);
		}

		fos.close();
		fis.close();
	}

	// 基本字节流一次读写一个字节
	public static void method1(String srcString, String destString)
			throws IOException {
		FileInputStream fis = new FileInputStream(srcString);
		FileOutputStream fos = new FileOutputStream(destString);

		int by = 0;
		while ((by = fis.read()) != -1) {
			fos.write(by);
		}

		fos.close();
		fis.close();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值