JAVA笔记(13)异常, IO(上)

文章目录

第1章异常

1.1异常的概述和继承体系

1.1.1 异常详解

异常的概念:
异常:就是程序出现了不正常的情况。
例如:ArithmeticException:当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。

常见的异常有:
IndexOutOfBoundsException、NullPointerException、StringIndexOutOfBoundsException

异常的体系的介绍:
Throwable 类是 Java 语言中所有错误或异常的超类。

Error 是 Throwable 的子类,用于指示合理的应用程序不应该试图捕获的严重问题。
也就是说针对程序发生了Error的情况,Java程序本身是无能为力的,比如说:硬件层面的问题,内存不足等。
所以,针对Error的问题我们不处理。

Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。
也就是说针对程序发生了Exception的情况,是我们需要处理的问题。

Exception的分类:
运行期的异常(RunTimeException):在编译期是不处理的,在程序运行时候出现了问题,需要我们回来修改代码。
编译期的异常(非RunTimeException):在编译期就必须处理,否则程序不能通过编译,就更不能正常的执行了。

1.1.2 案例代码

package javalearning;
public class ExceptionDemo {
	public static void main(String[] args) {
		method();
	}
	
	public static void method() {
		int a = 10;
		int b = 5;
		//b = 0;
		System.out.println(a/b);
	}
}

1.2JVM针对异常的默认处理方式

1.2.1JVM默认如何处理异常?

如果程序出现了问题,我们没有做任何的处理,最终JVM会做出默认的处理。

默认处理方案:
把异常的名称,异常的原因,异常出现的位置等信息在控制台输出,然后让程序停止执行

1.2.2案例代码

package javalearning;
/*
控制台:
程序开始执行
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at javalearning.ExceptionDemo2.method(ExceptionDemo2.java:24)
	at javalearning.ExceptionDemo2.main(ExceptionDemo2.java:17)


	java.lang.ArithmeticException:异常的类名,包括包名
 	 / by zero:异常的原因,被0除
 	at javalearning.ExceptionDemo2.method(ExceptionDemo2.java:17):异常的位置(包,类,方法,行数)
如果程序出现了问题,我们没有做任何的处理,最终JVM会做出默认的处理。
默认处理方案:
把异常的名称,异常的原因,异常出现的位置等信息在控制台输出,然后让程序停止执行
*/
public class ExceptionDemo2 {
	public static void main(String[] args) {
		System.out.println("程序开始执行");
		method();
		System.out.println("程序结束执行");
	}
	
	public static void method() {
		int a = 10;
		int b = 0;
		System.out.println(a/b);
	}
}

1.3异常处理方案try_catch

1.3.1 try…catch的格式和执行流程

格式:

try {
	可能出现异常的代码;
}catch(异常类名  变量名) {
	异常的处理代码;
}
  

执行流程:
程序从try开始执行,执行到哪里出现了问题,就会跳转到catch里面执行。
执行完毕后,程序还能继续往下执行。

捕获异常后, 如何处理?
public void printStackTrace():把异常的错误信息输出在了控制台。
在实际开发中,我们遇见了异常,会给出一个页面进行提示,而我们目前做不了,
所以,就用异常对象调用printStackTrace()就可以了。

1.3.1.1 案例代码
package javalearning;
/*
 * 异常处理:
 * 方案1:try...catch...
 * 
 * 格式:
 * 		try {
 * 			可能出现异常的代码;
 * 		}catch(异常类名  变量名) {
 * 			异常的处理代码;
 * 		}
 * 
 * 执行流程:
 * 		程序从try开始执行,执行到哪里出现了问题,就会跳转到catch里面执行。
 * 		执行完毕后,程序还能继续往下执行。
 * 
 * public void printStackTrace():把异常的错误信息输出在了控制台。和JVM的默认处理方式效果一样,但是默认的方式会子啊异常出现后让程序停止执行,而这个方法可以继续往下执行程序。
 * 在实际开发中,我们遇见了异常,会给出一个页面进行提示,而我们目前做不了,
 * 所以,就用异常对象调用printStackTrace()就可以了。
 * 这样做了以后,我们的程序还可以继续往下执行。
 */
public class ExceptionDemo3 {
	public static void main(String[] args) {
		System.out.println("程序开始执行");
		method();
		System.out.println("程序结束执行");
	}
	
	public static void method() {
		try{
			int a = 10;
			int b = 0;
			System.out.println("1处执行");
			System.out.println(a/b);
			System.out.println("2处执行");
		}catch(ArithmeticException e) {
			System.out.println("除数不能为0");
		}
		System.out.println("3处执行");
		
		try{
			int a = 10;
			int b = 0;
			System.out.println(a/b);//发生异常,就抛出次异常类的一个实例(也就是对象),catch就会接收到这个对象,e就是接收的对象,对象可以调用方法
		}catch(ArithmeticException e) {
			e.printStackTrace();
		}
	}
}
/*
程序开始执行
1处执行
除数不能为0
3处执行
java.lang.ArithmeticException: / by zero
	at javalearning.ExceptionDemo3.method(ExceptionDemo3.java:44)
	at javalearning.ExceptionDemo3.main(ExceptionDemo3.java:25)
程序结束执行

*/

1.3.2 try…catch处理方式&JVM的默认处理方式有什么不同

首先要明确try…cathc处理方式的特点, 产生了问题, 是自己将问题处理掉, 不影响后续代码的运行.
JVM默认处理方式是将程序终止, 并将异常信息打印在控制台.
但这种方式很显然用户体验度不佳, 所以这时候就可以考虑使用try…cathc将问题捕获并处理掉.
这样就不会影响程序的继续执行了

1.4编译时异常和运行时异常的区别

1.4.1 异常的两大分类指的是?

编译时异常
运行时异常

1.4.2 两种异常的区别是?

Java中的异常被分为两大类:编译时异常和运行时异常。
所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常都是编译时异常

编译时异常:Java程序必须显示处理,否则程序就会发生错误的一个提示,无法通过编译
运行时异常:Java程序无需显示处理,也可以和编译时异常一样处理

1.4.3 案例代码

package javalearning;
public class ExceptionDemo4 {
	public static void main(String[] args) {
		System.out.println("程序开始执行");
		//method();
		method2();
		System.out.println("程序结束执行");
	}
	
	//编译时异常ParseException
	public static void method() {
		try{
			//String s = "2088-08-08";
			String s = "abcd";
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date d = sdf.parse(s);//报错 Unhandled exception type ParseException
			System.out.println(d);
		}catch(ParseException e) {
			e.printStackTrace();
		}
	}
	
	//运行时异常
	public static void method2() {
		try{
			int a = 10;
			int b = 0;
			System.out.println(a/b);
		}catch(ArithmeticException e) {
			e.printStackTrace();
		}
	}
}

1.5异常处理方案throws

1.5.1 为什么要有throws处理方式?

我们通过try…catch可以对异常进行处理了,但是并不是所有的时候我们都有权限进行异常的处理。也就是说,有些时候我们处理不了,但是,这个时候异常时存在的,不处理也不行,怎么办?
这个时候,Java就提供了throws的处理方案。

1.5.2 throws使用的格式&注意事项?

格式:
throws 异常类名
注意:这个格式必须跟在方法的括号的后面

注意:
编译时异常时必须要进行处理的,两种处理方案:try…catch…或者throws
如果你采用了throws这种方案,将来谁调用,还得进行处理。

运行时异常可以不用处理,出现问题后我们需要回来修改代码。

1.5.3 案例代码

public class ExceptionDemo5 {
	public static void main(String[] args) {
		System.out.println("程序开始执行");
		try {
			method();//method()本身有编译时期的异常且没有做try...catch处理,是使用throws处理的,所以这里调用时必须处理,这里可以使用try...catch也可以使用throws,推荐用try...catch
		} catch (ParseException e) {
			e.printStackTrace();
		}
		method2();//method2()也抛出了一个异常,但是是运行期异常,运行期异常在编译时是不需要处理的。所以这里没报错
		System.out.println("程序结束执行");
	}
	
	//编译时异常
	public static void method() throws ParseException {
		String s = "2088-08-08";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date d = sdf.parse(s);
		System.out.println(d);
	}
	
	//运行时异常
	public static void method2() throws ArithmeticException {
		int a = 10;
		int b = 0;
		System.out.println(a/b);
	}
	
}

第2章File类

2.1 File类的概述和构造方法

2.1.1 File类的概述

在java.io包下,使用时要导包
File:文件和目录路径名的抽象表示形式
也就是说文件和目录是可以通过File封装成对象的
目录:其实就是文件夹

2.1.2 File类的构造方法

file构造方法:
File(String pathname):通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child):根据 parent 路径名字符串(这里一定是一个目录名字,不能是文件名,因为文件里面是不会有东西的)和 child 路径名字符串创建一个新 File 实例。
File(File parent, String child):根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例

2.2.3 案例代码

public class FileDemo {
	public static void main(String[] args) {
		//File(String pathname)
		File f1 = new File("d:\\aa\\b.txt");//只是把字符串路径封装成对象,并没有对b.txt这个文件进行创建或者删除或者做任何操作。这时候的f1仅仅只是一个抽象表现形式而已
		
		//File(String parent, String child)
		File f2 = new File("d:\\aa","b.txt");
		
		//File(File parent, String child)
		File f3 = new File("d:\\aa");
		File f4 = new File(f3,"b.txt");
		
		//上面的f1,f2,f4其实做的是同样的事情,就是把d:\\aa\\b.txt转换为了一个File对象
	}
}

2.2 File类的创建功能

2.2.1 方法摘要

创建功能
public boolean createNewFile():创建文件
如果文件不存在,创建文件并返回true
如果文件存在,创建文件失败并返回false

public boolean mkdir():创建目录
	如果目录不存在,创建目录并返回true
	如果目录存在,创建目录失败并返回false

public boolean mkdirs():创建多级目录

2.2.2 案例代码

public class FileDemo {
	public static void main(String[] args) throws IOException {
		//需求1:我要在d盘目录下创建一个文件a.txt
		File f1 = new File("d:\\a.txt");
		System.out.println("createNewFile:"+f1.createNewFile());
		
		//需求2:我要在d盘目录下创建一个目录bb
		File f2 = new File("d:\\bb");
		System.out.println("mkdir:"+f2.mkdir());
		System.out.println("-----------------");
		
		//需求3:我要在d盘目录下创建一个多级目录cc\\dd
//		File f3 = new File("d:\\cc\\dd");
//		System.out.println("mkdir:"+f3.mkdir());//mkdir:false并没有创建成功,因为f3其实最终代表的是dd这个目录,但是d盘中连cc这个目录都不存在,更不会去创建dd这个目录了
		//需要一步一步的实现
//		File f3 = new File("d:\\cc");
//		File f4 = new File("d:\\cc\\dd");
//		System.out.println("mkdir:"+f3.mkdir());//mkdir:true
//		System.out.println("mkdir:"+f4.mkdir());//mkdir:true
		//但如果我的目录级别太多,就不方便向上面那样一步一步实现了。
		//我们有一步到位的实现方法,创建多级目录
		File f3 = new File("d:\\cc\\dd");
		System.out.println("mkdirs:"+f3.mkdirs());
		
		//需求4:我要在d盘目录下创建一个文件ee\\f.txt。注意这里是造文件,不是目录
		File f4 = new File("d:\\ee");
		File f5 = new File("d:\\ee\\f.txt");
		System.out.println("mkdir:"+f4.mkdir());
		System.out.println("createNewFile:"+f5.createNewFile());
	}
}

2.3 File类的删除功能

2.3.1 相对路径&绝对路径

路径的问题:
绝对路径:是以盘符开始的路径。d:\aa\b.txt
相对路径:不以盘符开始。没指定路径时,是相对于当前的项目而言,在项目的目录下创建文件。如何显示出来呢?刷新项目就可以了,如:ecslipse中选中项目myFile右键refresh即可

2.3.2 方法摘要&注意事项

删除功能
public boolean delete():删除文件和目录

注意:
如果一个目录中有内容(这个内容可以是目录也可以是文件),就不能直接删除。
应该先删除目录中的内容,最后才能删除目录。

2.3.4 案例代码

public class FileDemo {
	public static void main(String[] args) throws IOException {
		// //需求1:我要创建一个文件a.txt
		// File f1 = new File("a.txt");
		// System.out.println("createNewFile:"+f1.createNewFile());//文件创建在当前的项目目录中
		//
		// //需求2:我要创建一个目录bb
		// File f2 = new File("bb");
		// System.out.println("mkdir:"+f2.mkdir());//目录bb创建在当前的项目目录中
		// System.out.println("-----------------");
		//
		// //需求3:我要创建一个文件cc\\d.txt
		// File f3 = new File("cc");
		// File f4 = new File("cc\\d.txt");
		// System.out.println("mkdir:"+f3.mkdir());
		// System.out.println("createNewFile:"+f4.createNewFile());
		// System.out.println("-----------------");

		// public boolean delete():删除文件和目录
		// 需求1:我要删除a.txt这个文件
		File f1 = new File("a.txt");
		System.out.println("delete:" + f1.delete());
		
		//需求2:我要删除bb这个目录
		File f2 = new File("bb");
		System.out.println("delete:"+f2.delete());
		System.out.println("--------------------");
		
		//需求3:我要删除cc这个目录
		File f3 = new File("cc");
		System.out.println("delete:"+f3.delete());//并没有删除cc,因为cc里面是有内容的,有一个文件,因此不能直接删除cc
		//思路:先删除d.txt这个文件,再删除cc这个目录
		File f4 = new File("cc\\d.txt");//这里必须把cc也写上,否则无法删除
		File f5 = new File("cc");
		System.out.println("delete:"+f4.delete());//delete:true

		System.out.println("delete:"+f5.delete());//delete:true
	}
}

2.4 File类的判断和获取功能

2.4.1 方法摘要(以下方法是File类当中必须要掌握的)

判断功能
public boolean isDirectory():判断是否是目录
public boolean isFile():判断是否是文件
public boolean exists():判断是否存在
获取功能
public String getAbsolutePath():获取绝对路径
public String getPath():获取相对路径
public String getName():获取名称

2.4.2 案例代码

public class FileDemo {
	public static void main(String[] args) {
		//创建File对象
		File f = new File("aaa\\bbb.txt");
		
		//判断功能
		System.out.println("isDirectory:"+f.isDirectory());//f
		System.out.println("isFile:"+f.isFile());//t
		System.out.println("exists:"+f.exists());//t
		System.out.println("------------------");
		
		//获取功能
		System.out.println("getAbsolutePath:"+f.getAbsolutePath());
		System.out.println("getPath:"+f.getPath());
		System.out.println("getName:"+f.getName());
	}
}

第3章IO(字节流)

3.1 IO流的概述和分类

3.1.1 什么是IO流,其作用为?

IO可以拆开来理解
I ---- Input -> 输入 读取
O ---- Output -> 输出 写出

读取和写出都是针对数据而言的, 所以, IO流就是用来处理设备之间的数据传输。输入输出是站在java程序的角度看的,输入java程序和输入java程序

常见应用:

文件复制
文件上传
文件下载

在这里插入图片描述

3.1.2 IO流的分类

按照类型分:
字节流
字符流 (字符流数据通过Windows自带的记事本软件打开是可以读懂里面内容的)
按照流向分:
输入流 : 用来读取数据的(是站在java程序的角度看的,输入java程序)
输出流 : 用来写数据的

3.2 FileOutputStream写数据

3.2.1 字节流&字符流的抽象父类

字节流:
InputStream 字节输入流
OutputStream 字节输出流
字符流:
Reader 字符输入流
Writer 字符输出流

3.2.2 字节流写出数据OutputStream

字节流写数据
OutputStream:此抽象类是表示输出字节流的所有类的超类。在java.io包下,使用时要导包。
FileOutputStream:文件输出流是用于将数据写入 File,继承OutputStream

FileOutputStream的构造方法:
FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。

字节流写数据的步骤:
A:创建字节输出流对象
B:调用写数据的方法
C:释放资源

3.2.3 案例代码

public class FileOutputStreamDemo {
	public static void main(String[] args) throws IOException {
	//没写write那句时这里抛出的异常是FileNotFoundException
	//写了write这句后,要求抛出异常IOException,因为IOException是
	//FileNotFoundException的父类,所以这里只用写throws IOExceptio即可
		//创建字节输出流对象
		FileOutputStream fos = new FileOutputStream("a.txt");
		/*
		 * 创建字节输出流对象做了这样的三件事情:
		 * A:调用系统功能创建了文件a.txt
		 * B:创建字节输出流对象fos
		 * C:让fos这个对象指向a.txt这个文件
		 */
		
		//write(int b) 将指定字节写入此文件输出流。
		fos.write(65);//在该文件中存储的数据也是65,只不过打开文件时,文件的编码或解码方式把65识别为"A",给我们看到是“A”,而不是65
		fos.write(66);//文件中展示的是“AB”
		
		//最后我们还要做一个事情。因为这个文件是系统帮我们创建的,因此最后要通知系统释放相关资源
		//close() 关闭此文件输出流并释放与此流有关的所有系统资源。
		fos.close();//文件中仍然是"AB"。
	}
}

3.3 FileOutputStream写数据的三种方式.

3.3.1 方法摘要

构造方法:
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
写出数据的三个方法:
public void write(int b):一次写一个字节
public void write(byte[] b):一次写一个字节数组
public void write(byte[] b,int off,int len):一次写一个字节数组的一部分

String类中的方法:
byte[] getBytes() 将字符串转换为字节数组

3.3.2 案例代码

package javalearning;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 构造方法:
 * FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
 * FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
 * 
 * 写数据的方法:
 * public void write(int b):一次写一个字节
 * public void write(byte[] b):一次写一个字节数组
 * public void write(byte[] b,int off,int len):一次写一个字节数组的一部分 (从索引off开始,一共len个元素)
 * 
 * 字节流写数据的步骤:
 * 		A:创建字节输出流对象
 * 		B:调用写数据的方法
 * 		C:释放资源
 */
public class FileOutputStreamDemo2 {
	public static void main(String[] args) throws IOException {
		//创建字节输出流对象
		//FileOutputStream(String name) 
		FileOutputStream fos = new FileOutputStream("b.txt");//这里要求抛一个异常throws FileNotFoundException,只不过后面写write要抛出的异常是它的父类IOException所以就不用写FileNotFoundException了。		
	
		
		//FileOutputStream(File file) 
//		File file = new File("b.txt");
//		FileOutputStream fos = new FileOutputStream(file);
//		FileOutputStream fos = new FileOutputStream(new File("b.txt"));//这一步等价于上面两步,那这步是否等价于FileOutputStream fos = new FileOutputStream("b.txt");呢?
        //按住Ctrl查看FileOutputStream源码如下:
/* public FileOutputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null, false);
    }
*/
   		//把b.txt传给name了。其实相当于new File("b.txt")。因此这两种构造方法实际上是一模一样的。
		
		//public void write(int b):一次写一个字节
//		fos.write(65);
		
		//public void write(byte[] b):一次写一个字节数组
//		byte[] bys = {65,66,67,68,69};
//		fos.write(bys);
		//需求:我如果是一个字符串的数据,能写吗?
		//给出的方法并不能直接写字符串,但是我们可以将字符串转为字节数组
		//String -- byte[]
		//String类中有一个方法:public byte[] getBytes()将字符串转为字节数组
//		byte[] bys = "ABCDE".getBytes();
//		fos.write(bys);
//		fos.write("ABCDE".getBytes());//这句等价于上面两句
		
		//public void write(byte[] b,int off,int len):一次写一个字节数组的一部分
		fos.write("ABCDE".getBytes(),0,3);//写了ABC
		
		//释放资源
		fos.close();
	}
}

3.4 FileOutputStream如何实现换行和追加写数据

3.4.1 如何实现数据的换行

不同的操作系统,针对换行的符号识别是不一样的。
windows:\r\n
linux:\n
mac:\r
eclipse自带记事本软件的和高级记事本可以将以上的3种符号都识别为换行,但是记事本是windows下的,如果使用\n换行的话,用记事本打开文件没法显示换行

3.4.2 如何实现数据的追加写入?

用构造方法FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。

3.4.3 案例代码

public class FileOutputStreamDemo3 {
	public static void main(String[] args) throws IOException {
		//创建字节输出流对象
		//FileOutputStream fos = new FileOutputStream("c.txt");
		//FileOutputStream(String name, boolean append) 
		//如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。(不给第二个参数则默认为false)
		FileOutputStream fos = new FileOutputStream("c.txt",true);
		
		//调用写数据的方法
		for(int x=0; x<10; x++) {
			fos.write("hello".getBytes());
			//加入换行符号
			fos.write("\r\n".getBytes());
		}
		
		//释放资源
		fos.close();
	}
}

3.5 FileOutputStream写数据加入异常处理

3.5.1 try…catch.finally

格式:

try{
			可能发生问题的代码
}catch(){
	处理异常代码
}finally{
		一定会被执行的代码.   // 通常用于释放资源, 做善后的动作
}

3.5.2 案例代码

package javalearning;

import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 字节流写数据加入异常处理
 */
public class FileOutputStreamDemo4 {
	public static void main(String[] args) {
//		FileOutputStream fos = new FileOutputStream("d.txt");
//		fos.write("hello".getBytes());
//		fos.close();
		
		//分开做异常处理
//		FileOutputStream fos = null;
//		//FileOutputStream fos;
//		try {
//			fos = new FileOutputStream("d.txt");
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		}
//		try {
//			fos.write("hello".getBytes());//报错:The local variable fos may not have been initialized。
//		//因为FileOutputStream fos;只是申明了fos,如果一进入第一个try就出现异常,
// 		//就会执行catch里的内容,try里的fos = new FileOutputStream("d.txt");初始化操作就执行不了。
//		//所以为了完成初始化,应该在一开始给它赋一个值FileOutputStream fos = null;就能解决此问题。(因为是引用类型,所以给它赋个null)
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		try {
//			fos.close();
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
		
		//分开做异常处理太麻烦了。



		//放在一起做异常处理
//		try{
//			FileOutputStream fos = new FileOutputStream("d.txt");
//			fos.write("hello".getBytes());
//			fos.close();
//		}catch(IOException e) {
//			e.printStackTrace();
//		}
		//这种方式代码虽然简洁了,但是如果try种有异常,则释放资源的动作可能未执行到,所以还不是最好的办法



		//try...catch...finally
		FileOutputStream fos = null;//final中的fos看不到try里的fos,所以要在try外面给一个fos。但是给了FileOutputStream fos;以后fos.close();还是报错,我们点一下鼠标,对fos.close();抛出一个异常,然后还是报错,The local variable fos may not have been initialized。,所以这里还要赋值一下

		try{
			//FileOutputStream fos = new FileOutputStream("d.txt");
			//fos = new FileOutputStream("z:\\d.txt");
			fos = new FileOutputStream("d.txt");
			fos.write("hello".getBytes());
		}catch(IOException e) {
			e.printStackTrace();
		}finally {
			if(fos!=null) {//如果前面是fos = new FileOutputStream("z:\\d.txt");,运行时这里会报错NUllPointException,因为不存在z盘,所以fos仍然为null,null调用方法肯定是空指针异常,所以要判断一下不为null
				//释放资源
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

3.6 FileInputStream读数据方式1一次读取一个字节

InputStream:此抽象类是表示字节输入流的所有类的超类。 在java.io包下,使用时要导包。
这是抽象类所以我们最终要使用他的具体子类FileInputStream :从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。

FileInputStream构造方法:
FileInputStream(String name) :通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream(File file) :通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。

FileInputStream读数据方法:
public int read():读取一个字节的数据,如果已到达文件末尾,则返回 -1。

3.6.1 字节流读取数据的三个步骤

字节流读数据的步骤:
A:创建字节输入流对象
B:调用读数据的方法
C:释放资源

3.6.2 案例代码

package javalearning;

import java.io.FileInputStream;
import java.io.IOException;

/*
 * 字节流读数据:InputStream
 * 
 * FileInputStream 从文件系统中的某个文件中获得输入字节
 * 
 * 构造方法:
 * 		FileInputStream(String name) :通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

 * 		FileInputStream(File file) :通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
 * 
 * 读数据方法:
 * public int read():读取一个字节的数据,如果已到达文件末尾,则返回 -1。 
 *
 * 字节流读数据的步骤:
 * 		A:创建字节输入流对象
 * 		B:调用读数据的方法
 * 		C:释放资源
 */
public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		//创建字节输入流对象
		FileInputStream fis = new FileInputStream("a.txt");//a.txt内容是ab
		
		/*
		//调用读数据的方法
		//public int read():读取一个字节的数据,如果已到达文件末尾,则返回 -1。 
		int by = fis.read();
		System.out.println(by);//97
		System.out.println((char)by);//a
		
		//再来读取一次
		by = fis.read();
		System.out.println(by);//98
		System.out.println((char)by);//b
		
		//发现读数据的代码的重复度很高,想用循环改进
		//但是我们不知道循环的结束条件
		//再来读取两次
		by = fis.read();
		System.out.println(by);//-1
		by = fis.read();
		System.out.println(by);//-1我们明白了读到文件末尾会返回-1,所以循环的结束条件是-1
		*/
		
//		int by = fis.read();
//		while(by != -1) {
//			System.out.print((char)by);
//			by = fis.read();
//		}
		
		//改进版本
		int by;
		while((by=fis.read())!=-1) {//fis.read()--by=fis.read()--by != -1
			System.out.print((char)by);
		}
		
		//释放资源
		fis.close();
	}
}

3.7 FileInputStream读数据方式2一次读取一个字节数组

3.7.1 方法摘要

public int read(byte[] b):
从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
返回值是读入缓冲区的字节总数,也就是实际的读取个数
如果因为已经到达文件末尾而没有更多的数据,则返回 -1。

3.7.2 案例代码

package javalearning_01;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * 字节流读数据:
 * 方式1:一次读取一个字节
 * 方式2:一次读取一个字节数组
 * 
 * public int read(byte[] b):
 * 		从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
 * 		返回值是读入缓冲区的字节总数,也就是实际的读取个数
 * 		如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
 */
public class FileInputStreamDemo2 {
	public static void main(String[] args) throws IOException {
		//创建字节输入流对象
		FileInputStream fis = new FileInputStream("b.txt");
		
		/*
		//调用读数据的方法
		//定义一个数组
		byte[] bys = new byte[5];
		
		//第一次读取
		int len = fis.read(bys);
		System.out.println(len);//5
		//我们读的内容在byte[]中,想看数组里面的数据,我们把byte[]转成字符串
		//byte[] -- String
		//String类中有这样的方法可以帮我们实现
		//String(byte[] bytes) :通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
		//String(byte[] bytes, int offset, int length):通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。 
		System.out.println(new String(bys));//hello
		
		//第二次读取
		len = fis.read(bys);
		System.out.println(len);//5
		System.out.println(new String(bys));//空白行和wor
		
		//第三次读取
		len = fis.read(bys);
		System.out.println(len);//4。虽然数组长度为5,输出的东西实际上也有5个,但是read返回的是本次实际的读取个数
		//System.out.println(new String(bys));//ld和在下一行的r。这个做法不合理,应该本次读了几个就输出几个。所以按照下面这行写比较好
		System.out.println(new String(bys,0,len));//ld
		
		//第四次读取
		len = fis.read(bys);
		System.out.println(len);//-1
		//第五次读取
		len = fis.read(bys);
		System.out.println(len);//-1
		*/
		
		/*因为是在windows下,所以换行符是\r\n
		 * hello\r\n
		 * world\r\n
		 * 
		 * 第一次读5个:hello
		 * 第二次读5个:\r\nwor  控制台显示的是:一行空白行和wor。
  		 * 第三次读5个:但是只剩"ld\r\n"这4个数据了,而数组长度为5,这次读到的4个数据覆盖了数组的前4位,数组最后一位没有被覆盖,还是上一次的最后一位,即r,所以这次读了以后数组变成ld\r\nr。控制台显示ld和在下一行的r。
		 */
		
		/*
		byte[] bys = new byte[5];
		int len = fis.read(bys);
		while(len != -1) {
			System.out.print(new String(bys,0,len));//注意,这里不是println,而是print
			len = fis.read(bys);
		}
		*/
		
		//最终版代码
		byte[] bys = new byte[1024]; //1024或者1024的整数倍
		//1G = 1024MB
		//1MB = 1024KB
		//...
		int len;
		while((len=fis.read(bys))!=-1) {
			System.out.print(new String(bys,0,len));//注意,这里不是println,而是print
		}
		
		//释放资源
		fis.close();
	}
}

3.8 字节流练习之复制文本文件

需求: 拷贝文本文件
分析:
第一步: 创建输入输出流对象关联数据源和数据目的
第二步: 定义字节数组,为了提高效率
第三步: 将数据通过while循环不断读取到字节数组中
第四步: 将数据从字节数组中取出并写出
第五步: 释放资源

3.8.1 案例代码

public class CopyTxtTest {
	public static void main(String[] args) throws IOException {
		//封装数据源
		FileInputStream fis = new FileInputStream("d:\\窗里窗外.txt");
		//封装目的地
		FileOutputStream fos = new FileOutputStream("林青霞.txt");
		
		//读写数据
		//方式1:一次读取一个字节
//		int by;
//		while((by=fis.read())!=-1) {
//			fos.write(by);
//		}
		
		//方式2:一次读取一个字节数组
		byte[] bys = new byte[1024];
		int len;
		while((len=fis.read(bys))!=-1) {
			fos.write(bys, 0, len);
		}
		
		//释放资源
		fos.close();
		fis.close();
	}
}

3.9 字节流练习之复制图片

思路:
同理3.8案例

3.9.1案例代码

public class CopyJpgTest {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		FileInputStream fis = new FileInputStream("d:\\mn.jpg");
		// 封装目的地
		FileOutputStream fos = new FileOutputStream("mn.jpg");

		// 读写数据
		// 方式1:一次读取一个字节,一次写一个字节(自己练习)
		// 方式2:一次读取一个字节数组,一次写一个字节数组的一部分
		byte[] bys = new byte[1024];
		int len;
		while ((len = fis.read(bys)) != -1) {
			fos.write(bys, 0, len);
		}

		// 释放资源
		fos.close();
		fis.close();
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值