IO流的个人总结

l/O流

1、IO流

1.1、概念

数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为 输入input 和 输出output ,即流向内存是输入流,流出内存的输出流。
Java中I/O操作主要是指使用 java.io 包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。

1.2、分类

根据数据的流向分为:输入流和输出流。
​ 输入流 :把数据从 其他设备 上读取到 内存 中的流。
​ 输出流 :把数据从 内存 中写出到 其他设备 上的流。
根据数据的类型分为:字节流和字符流。
​ 字节流 :以字节为单位,读写数据的流。
​ 字符流 :以字符为单位,读写数据的流。
在这里插入图片描述

2、字节流

一切文件(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都是按一个一个的字节存储的,所以传输文件的时候也是如此。所以,字节流可以传输任意文件数据。在操作流的时候,要了解到无论使用什么样的流对象,底层传输的始终为二进制数据。

2.1、字节输出流–OutputStream

该类是一个抽象类;表示字节输出流的所有类的超类,将指定的字节信息写出到目的文件。
类中定义了字节输出流的基本共性功能方法。
在这里插入图片描述

2.2、FileOutputStream类

OutputStream的子类,该类多用于将数据写出到文件

2.2.1、构造方法

在这里插入图片描述在这里插入图片描述

public static void main(String[] args) {
		//创建流对象时需要一个路径,路径中存在文件则清空文件数据,不存在则创建一个文件,
		//根据流对象创建输出流对象
		File file=new File("lina.txt");
		OutputStream out=new FileOutputStream(file);
		//根据文件名称创建输出流对象
		OutputStream out2=new FileOutputStream("lina.txt");
		}
2.2.2、写出字节数据

在这里插入图片描述

public static void main(String[] args) throws Exception {
		//创建流对象时需要一个路径,路径中存在文件则清空文件数据,不存在则创建一个文件,
		//根据流对象创建输出流对象
		File file=new File("lina.txt");
		OutputStream out=new FileOutputStream(file);
		//写出单个字节
		out.write(97);//写出第一个第1个字节到文件
		out.write(98);//写出第一个第2个字节到文件
		out.write(99);//写出第一个第3个字节到文件
		//写出字节数组
		String str="123";
		byte[] bs=str.getBytes();
		out.write(bs);
		//写出指定长度的字节数组
		out.write(bs, 0, 3);
		out.close();
		}
2.2.3、数据追加写出到文件

在这里插入图片描述
在这里插入图片描述

换行:Windows系统里,换行符号是 \r\n 。

out.write("\r\n".getBytes());
2.3、字节输入流–InputStream

该类是一个抽象类,表示字节输入流的所有类的超类;

可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。

在这里插入图片描述
在这里插入图片描述

2.4、FileInputSteam类

文件输入流,从文件中读取字节。

2.4.1、构造方法

在这里插入图片描述
在这里插入图片描述

2.4.2、读取字节的数据

在这里插入图片描述

public static void main(String[] args) throws IOException {
		//读取文件中的内容--
		File file=new File("lina.txt");
		if(file.exists()){
			//根据文件的对象创建一个字节输入流;读取的文件必须存在才能读
			InputStream in=new FileInputStream(file);
			//按字节读取--读取的结果提升为int类型;如果读取的结果是-1,代表读取文件到了结尾
			int num1=in.read();//读取第1个字节
			int num2=in.read();//读取第2个字节
			int num3=in.read();//读取第3个字节			
			System.out.println(num1+"=="+num2+"=="+num3);
			//按字节数组读取
			int len=(int) file.length();
			byte[] bs=new byte[len];
			in.read(bs);	
			String s=new String(bs);
			System.out.println(s);
			//读取指定长度的字节数组
			in.read(bs, 0, 5);
			in.close();
		}else{
			System.out.println("要读取的文件不存在!");
		}
	}
2.5、PS:所有流最后都要关闭
2.6、练习:复制文件
public class Test3 {
	public static void mycopy(String sourceFile,String muBiaoFile) throws IOException{
		//从硬盘读取文件到写入到内存中
		InputStream in=new FileInputStream(sourceFile);
		//从内存中写出到指定硬盘
		OutputStream out=new FileOutputStream(muBiaoFile);
		byte[] b=new byte[1024];
		while(in.read(b)!=-1){//==-1表示文件读取到了结尾
			out.write(b);
		}
		in.close();		
		out.close();
	}
	
	public static void main(String[] args) {
		try {
			mycopy("d:/Wildlife.wmv", "e:/Wildlife.wmv");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

3、字符流

当使用字节流读取文本文件时,当遇到遇到中文字符时,可能因为一个中文字符可能占用多个字节存储而出现问题。所以Java提供了字符流类,以字符为单位读写数据,专门用于处理文本文件。

3.1、字符输入流–Reader

java.io.Reader 是一个抽象类,该类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。

在这里插入图片描述
在这里插入图片描述

3.2、FileReader类

阅读字符文件的便利类。 该类的构造函数假定默认字符编码和默认字节缓冲区大小是适当的。

字节缓冲区:一个字节数组,用来临时存储字节数据。

字符编码:字节与字符的对应规则。

3.2.1、构造方法

在这里插入图片描述
在这里插入图片描述

public static void main(String[] args) throws FileNotFoundException {
		//根据文件对象创建---字符输入流
		File file=new File("lina.txt");
		Reader reader=new FileReader(file);
		//根据文件名称创建---字符输入流
		Reader reader2=new FileReader("lina.txt");
	}
3.2.2、读入方法

在这里插入图片描述

public static void main(String[] args) throws IOException {
		//根据文件对象创建---字符输入流
		File file=new File("lina.txt");
		Reader reader=new FileReader(file);
		//读取单个字符
		int num=reader.read();
		System.out.println(num);
		num=reader.read();
		System.out.println(num);
		num=reader.read();
		System.out.println(num);
		//读取字符数组
		char[] cs=new char[20];
		//read()返回值:读取到的真正的字符的个数
		int num2=reader.read(cs);
		System.out.println(num2);
		for (char c : cs) {
			System.out.println(c);
		}
		//读取指定长度的字符放入数组
		num2=reader.read(cs, 3, 10);
		reader.close();
	}
3.3、字符输出流–Writer

是一个抽象类,该抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字符输出流的基本共性功能方法。

在这里插入图片描述

3.4、FileWriter类

java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

3.4.1、构造方法

在这里插入图片描述
在这里插入图片描述

3.4.2、写出数据的方法
public static void main(String[] args) throws IOException {
		File file=new File("lina.txt");
		//根据文件对象创建---字符输出流
		Writer w=new FileWriter(file);
		//写出数据
		//写出字符串
		w.write("中国");
		//写出字符的数组	
		char[] cs={'你','好','啊','a'};
		w.write(cs);
		//写入整数,不是写入的数字,写入的是整数对应的字符
		w.write(97);
		w.flush();//刷新缓冲区,强行将缓冲区中的无内容写出到文件中;刷新之后的流依然可用
		w.close();//先刷新缓冲,再关闭流,流不可用了
		System.out.println("over");
	}

4、缓冲区

在基本的流对象基础之上创建而来的,是对基本流对象的一种增强。

4.1、概述

缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,

按照数据类型分类:

字节缓冲流: BufferedInputStream , BufferedOutputStream

字符缓冲流: BufferedReader , BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

4.2、字节缓冲流
4.2.1、构造方法

在这里插入图片描述

public static void main(String[] args) throws FileNotFoundException {
		File file=new File("lina.txt");
		//创建字节输入流
		InputStream in=new FileInputStream(file);
		//创建字节输出流
		OutputStream out=new FileOutputStream(file);
		//创建缓冲输入流
		BufferedInputStream bin=new BufferedInputStream(in);
		//创建缓冲输出流
		BufferedOutputStream bout=new BufferedOutputStream(out);	
	}
4.2.2、高效体现
public class Test5 {
	public static void mycopy(String sourceFile,String muBiaoFile) throws IOException{
		//从硬盘读取文件到写入到内存中
		InputStream in=new FileInputStream(sourceFile);
		//从内存中写出到指定硬盘
		OutputStream out=new FileOutputStream(muBiaoFile);
		byte[] b=new byte[100];
		long time1=System.currentTimeMillis();
		while(in.read(b)!=-1){//==-1表示文件读取到了结尾
			out.write(b);
		}
		long time2=System.currentTimeMillis();
		System.out.println(time2-time1+"----毫秒数");
		in.close();	
		out.close();
	}
	
	public static void main(String[] args) {
		try {
			mycopy("d:/test.wmv","e:/test.wmv");
			mycopy2("d:/test.wmv","e:/test.wmv");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void mycopy2(String sourceFile,String muBiaoFile) throws IOException {
		File file=new File(sourceFile);
		File file2=new File(muBiaoFile);
		//创建字节输入流
		InputStream in=new FileInputStream(file);
		//创建字节输出流
		OutputStream out=new FileOutputStream(file2);
		//创建缓冲输入流
		BufferedInputStream bin=new BufferedInputStream(in);
		//创建缓冲输出流
		BufferedOutputStream bout=new BufferedOutputStream(out);
		//复制一个视频
		byte[] bs=new byte[100];
		long time1=System.currentTimeMillis();
		while(bin.read(bs)!=-1){
			bout.write(bs);
		}
		System.out.println("over");
		long time2=System.currentTimeMillis();
		System.out.println(time2-time1+"----毫秒数");
		bin.close();
		bout.close();
	}
}
4.3、字符缓冲流
4.3.1、构造方法

在这里插入图片描述

4.3.2、独有方法

字符缓冲流的基本方法与普通字符流调用方式一致,不再列举。

接下来说明字符缓冲流独有的方法:

在这里插入图片描述

public static void main(String[] args) throws IOException {
		File file=new File("lina.txt");
		File file2=new File("lina2.txt");
		//字符输入流
		Reader read=new FileReader(file);
		//字符输出流
		Writer write=new FileWriter(file2);
		//缓冲输入流
		BufferedReader br=new BufferedReader(read);
		//缓冲输出流
		BufferedWriter bw=new BufferedWriter(write);
		//特有的读取一行
		String s=br.readLine();
		System.out.println(s);
		s=br.readLine();
		System.out.println(s);
		s=br.readLine();
		System.out.println(s);
		br.close();
		//写入一行
		bw.newLine();//相当于写入“\r\n”
		bw.write("aaaa");
		bw.newLine();
		bw.write("aaaa");
		bw.newLine();
		bw.write("aaaa");
		bw.close();
		System.out.println("over");
	}

5、转换流

5.1、字符编码和字符集

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制。

数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码 。反之,将存储在计算机中的二进制数按照。

某种规则解析显示出来,称为解码 。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

字符编码 Character Encoding : 就是一套自然语言的字符与二进制数之间的对应规则

5.2、字符集

字符集 Charset :也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有:ASCII字符集、GBK字符集、Unicode字符集等。

当指定了编码,它所对应的字符集自然就指定了,所以编码很重要。

下图是字符集与编码的对照。

在这里插入图片描述

  • ASCII字符集**

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。

  • ISO-8859-1*字符集:

拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。ISO-5559-1使用单字节编码,兼容ASCII编码。

  • GBxxx字符集:

GB就是国标的意思,是为了显示中文而设计的一套字符集。

GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。

GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。

GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。

  • Unicode*字符集

Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。

UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:

  1. 128个US-ASCII字符,只需一个字节编码。

  2. 拉丁文等字符,需要二个字节编码。

  3. 大部分常用字(含中文),使用三个字节编码。

  4. 其他极少使用的Unicode辅助字符,使用四字节编码

5.3、编码转换的问题

不同编码格式会引发乱码问题,所以出现了转换流。转换流是字节与字符间的桥梁!

在这里插入图片描述

5.4、InputStreamReader类

转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

5.4.1、构造方法

在这里插入图片描述
在这里插入图片描述
InputStreamReader isr = new InputStreamReader(new FileInputStream(“lina.txt”));

InputStreamReader isr2 = new InputStreamReader(new FileInputStream(“lina.txt”) , “GBK”);

5.4.2、按照指定编码读取
public class Ttest6 {
	public static void main(String[] args) throws IOException {
		InputStream in=new FileInputStream("lina.txt");//文件编码格式是UTF8
		InputStreamReader r1=new InputStreamReader(in,"GBK");
		char[] bs=new char[1024];
		while(r1.read(bs)!=-1){//使用GBK格式读取的结果会乱码
			System.out.println(new String(bs));
		}
		System.out.println("read over");
		r1.close();
	}
}
5.5、OutputStreamWriter类

转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

5.5.1、构造方法

在这里插入图片描述

public static void write() throws IOException{
		OutputStream out=new FileOutputStream("lina.txt");
		OutputStreamWriter w=new OutputStreamWriter(out, "GBK");
		w.write("你好你好你好你好你好你好");
		w.close();
		System.out.println("write over");
}
public class Ttest6 {
	
	public static void read(String fileName,String charsetName) throws IOException{
		InputStream in=new FileInputStream(fileName);
		InputStreamReader r1=new InputStreamReader(in,charsetName);
		char[] bs=new char[1024];
		while(r1.read(bs)!=-1){//使用GBK格式读取的结果会乱码
			System.out.println(new String(bs));
		}
		System.out.println("read over");
		r1.close();
	}
	
	public static void write(String fileName,String charsetName) throws IOException{
		OutputStream out=new FileOutputStream(fileName);
		OutputStreamWriter w=new OutputStreamWriter(out, charsetName);
		w.write("你好你好你好你好你好你好");
		w.close();
		System.out.println("write over");
	}
	public static void main(String[] args) throws IOException {
		write("lina.txt","GBK");
		read("lina.txt","utf8");
	}
}

6、过滤流

DataInputStream类:提供了往各种输入流对象中读取各种类型的数据的方法

DataOutputStream类:提供了往各种输出流对象中写出各种类型的数据的方法

6.1、构造方法
InputStream in=new FileInputStream("lina.txt");
OutputStream out=new FileOutputStream("lina.txt");
DataInputStream din=new DataInputStream(in);
DataOutputStream dout=new DataOutputStream(out);
6.2、其他方法

DataInputStream类中的读取数据的方法:
在这里插入图片描述
DataOutputStream类的写出方法:
在这里插入图片描述

public static void fun2() throws IOException {
		OutputStream out = new FileOutputStream("lina.txt");
		// 过滤流--封装了一些方法专门针对各种数据类的写入和写出
		DataOutputStream dout = new DataOutputStream(out);
		/*dout.writeUTF("utf你好!\r\n");
		dout.write("你好!\r\n".getBytes());*/
		dout.writeInt(100);
		dout.writeDouble(3.5);
		dout.writeBoolean(true);
		dout.close();
		System.out.println("write over");
		InputStream in = new FileInputStream("lina.txt");
		DataInputStream din = new DataInputStream(in);
		/*String s1 = din.readUTF();
		System.out.println(s1);
		byte[] bs = new byte[1024];
		while (din.read(bs) != -1) {
			System.out.print(new String(bs));
		}*/
		int num = din.readInt();
		double num2 = din.readDouble();
		boolean res = din.readBoolean();
		System.out.println(num);
		System.out.println(num2);
		System.out.println(res);
		System.out.println("read over");
		din.close();
	}

7、序列化与反序列化

7.1、概述

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该 对象的数据 、 对象的类型 和 对象中存储的属性 等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。 对象的数据 、 对象的类型 和 对象中存储的数据 信息,都可以用来在内存中创建对象。

7.2、序列化

把Java对象转换为字节序列的过程称为对象的序列化。

7.3、序列化的条件

一个对象要想序列化,必须满足两个条件:

该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出 NotSerializableException 。

该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬的,使用 transient 关键字修饰:为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

public class Student implements Serializable{
	private String name;
	private Integer age;
	private Teacher teacher;
}
public class Teacher implements Serializable{
	private String name;
	private Integer age;
}
public static void main(String[] args) {
		Teacher t=new Teacher("lina", 20);
		Student s1 = new Student("baoyu", 16,t);
		try (OutputStream out = new FileOutputStream("lina.txt");
				ObjectOutputStream o = new ObjectOutputStream(out);) {
			// 对象的序列化--将java对象从内存存储到硬盘
			o.writeObject(s1);
			System.out.println("over");
		} catch (Exception e) {
			e.printStackTrace();
		}
		try (
			InputStream in=new FileInputStream("lina.txt");
			ObjectInputStream i=new ObjectInputStream(in);
				){
			//对象的反序列化--从硬盘文件读取到内存中
			Object obj=i.readObject();
			if(obj!=null && obj instanceof Student){
				Student s=(Student) obj;
				System.out.println(s);
			}
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

8、Properties

8.4、概述

主要用于读取项目的配置文件,配置文件以.properties结尾的文件和xml文件。

8.5、构造方法

在这里插入图片描述

8.6、常用方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值