【Java网络编程与IO流】Java中IO流分为几种?字符流、字节流、缓冲流、输入流、输出流、节点流、处理流

Java网络编程与IO流目录:

【Java网络编程与IO流】Java中IO流分为几种?字符流、字节流、缓冲流、输入流、输出流、节点流、处理流

这里写图片描述

摘自大佬的文章 [吃透Java IO:字节流、字符流、缓冲流](
摘自大佬的文章 吃透Java IO:字节流、字符流、缓冲流

1.Java的IO流是什么?

IO:即in和out,输入和输出,指的是应用程序和外部设备之间的数据传递;

Java是通过流来处理IO的,流(Stream)是一个抽象的概念,是指一连串的树(字符或字节),是以先进先出的方式发送信息的通道;

一般流有以下特性:

  • 先进先出:最先写入输出流的数据最先被输入流读取到;
  • 顺序存取:可以一个接一个的往流中写入一串字节,读出时也会按写入顺序读取一串字节,不能随机访问中间的数据。
  • 只读或者只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能。
2.IO流的分类:
  • 按数据流的方向:输入流和输出流
  • 按处理数据单位:字节流和字符流
  • 按功能:节点流、处理流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GnoK555J-1606568015633)(C:\Users\lcz\AppData\Roaming\Typora\typora-user-images\image-20201128195110397.png)]

a.输入流与输出流

输入与输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SKw7Vb4O-1606568015635)(C:\Users\lcz\AppData\Roaming\Typora\typora-user-images\image-20201128195612843.png)]

b.字节流与字符流

两者的用法几乎一样,区别在于字节流和字符流所操作的数据单位不同,字节流操作的数据单位是8位的字节,字符流操作的数据单位是16位的字符。

为什么有了字节流还要推出字符流?

Java中字符是采用Unicode标准,在Unicode编码中,一个英文为一个字节,一个中文为两个字节。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZGf1EY8g-1606568015637)(C:\Users\lcz\AppData\Roaming\Typora\typora-user-images\image-20201128200137240.png)]

为了更加方便的处理中文这些字符,Java推出了字符流。

补充:在UTF-8中,一个中文字符是3个字节。

字节流和字符流的区别是什么?

  • 字节流可以处理一切文件,而字符流只能处理纯文本文件;例如字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如txt文件。
  • 字节流本身没有缓冲区,缓冲字节流相比于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相比于字符流提升没有那么大。
c.节点流和处理流
  • 节点流:直接操作数据读写的流类,比如FileInputStream

  • 处理流:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能,例如BufferedInputStream(缓冲字节流)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmipRycd-1606568015640)(C:\Users\lcz\AppData\Roaming\Typora\typora-user-images\image-20201128200949185.png)]

节点流和处理流应用了Java的装饰者设计模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WvPCu7l1-1606568015642)(C:\Users\lcz\AppData\Roaming\Typora\typora-user-images\image-20201128202145901.png)]

  • 抽象组件(InputStream) :装饰者模式中的超类,它只有一个抽象方法read(),子类都需要对该方法进行处理
  • 被装饰者(FileInputStream , ByteArrayInputStream , StringBufferInputStream) :拥有通用实现read()基本方法
  • 装饰者组件(FilterInputStream) :定义具体装饰者的行为规范,可以做统一基础处理。
  • 具体装饰(BufferedInputStream , DataInputStream , Base64InputStream) :具体的装饰类,拥有对流的读操作做完成具体拓展能力。

装饰者模式让我们可以有不同的被装饰者,例如FileInputStream,并且如果想使用缓冲功能那么只需写一下代码 :

new BufferedInputStream(new FileInputStream(new File("path")));1

也可以对上面代码再进行加工,简单的加密处理 :

new Base64InputStream(new BufferedInputStream(new FileInputStream(new File(""))),0)1

哪怕你突然改需求了,读取的对象不是文件,而是文本或字符,那么可以轻松的将代码改为 :

new Base64InputStream(new BufferedInputStream(new StringBufferInputStream("str")),0)
d.什么是缓冲流?

程序与磁盘的交互相对于内存运算是很慢的,容易成为程序的性能瓶颈。减少程序与磁盘的交互,是提升程序效率一种有效手段。缓冲流,就应用这种思路:普通流每次读写一个字节,而缓冲流在内存中设置一个缓存区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。这样,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。

在这里插入图片描述

3.Java中IO流的例子

文本读写的例子,将“松下问童子,言师采药去。只在此山中,云深不知处。”写入本地文本,然后再从文件读取内容并输出到控制台。

1、FileInputStream、FileOutputStream(字节流)

字节流的方式效率较低,不建议使用

public class IOTest {
	public static void main(String[] args) throws IOException {
		File file = new File("D:/test.txt");

		write(file);
		System.out.println(read(file));
	}

	public static void write(File file) throws IOException {
		OutputStream os = new FileOutputStream(file, true);

		// 要写入的字符串
		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
		// 写入文件
		os.write(string.getBytes());
		// 关闭流
		os.close();
	}

	public static String read(File file) throws IOException {
		InputStream in = new FileInputStream(file);

		// 一次性取多少个字节
		byte[] bytes = new byte[1024];
		// 用来接收读取的字节数组
		StringBuilder sb = new StringBuilder();
		// 读取到的字节数组长度,为-1时表示没有数据
		int length = 0;
		// 循环取数据
		while ((length = in.read(bytes)) != -1) {
			// 将读取的内容转换成字符串
			sb.append(new String(bytes, 0, length));
		}
		// 关闭流
		in.close();

		return sb.toString();
	}
}

2、BufferedInputStream、BufferedOutputStream(缓冲字节流)

缓冲字节流是为高效率而设计的,真正的读写操作还是靠FileOutputStreamFileInputStream,所以其构造方法入参是这两个类的对象也就不奇怪了。

public class IOTest {

	public static void write(File file) throws IOException {
		// 缓冲字节流,提高了效率
		BufferedOutputStream bis = new BufferedOutputStream(new FileOutputStream(file, true));

		// 要写入的字符串
		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
		// 写入文件
		bis.write(string.getBytes());
		// 关闭流
		bis.close();
	}

	public static String read(File file) throws IOException {
		BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));

		// 一次性取多少个字节
		byte[] bytes = new byte[1024];
		// 用来接收读取的字节数组
		StringBuilder sb = new StringBuilder();
		// 读取到的字节数组长度,为-1时表示没有数据
		int length = 0;
		// 循环取数据
		while ((length = fis.read(bytes)) != -1) {
			// 将读取的内容转换成字符串
			sb.append(new String(bytes, 0, length));
		}
		// 关闭流
		fis.close();

		return sb.toString();
	}
}
12345678910111213141516171819202122232425262728293031323334

3、InputStreamReader、OutputStreamWriter(字符流)

字符流适用于文本文件的读写OutputStreamWriter类其实也是借助FileOutputStream类实现的,故其构造方法是FileOutputStream的对象

public class IOTest {
	
	public static void write(File file) throws IOException {
		// OutputStreamWriter可以显示指定字符集,否则使用默认字符集
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");

		// 要写入的字符串
		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
		osw.write(string);
		osw.close();
	}

	public static String read(File file) throws IOException {
		InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
		// 字符数组:一次读取多少个字符
		char[] chars = new char[1024];
		// 每次读取的字符数组先append到StringBuilder中
		StringBuilder sb = new StringBuilder();
		// 读取到的字符数组长度,为-1时表示没有数据
		int length;
		// 循环取数据
		while ((length = isr.read(chars)) != -1) {
			// 将读取的内容转换成字符串
			sb.append(chars, 0, length);
		}
		// 关闭流
		isr.close();

		return sb.toString()
	}
}
12345678910111213141516171819202122232425262728293031

4、字符流便捷类

Java提供了FileWriterFileReader简化字符流的读写,new FileWriter等同于new OutputStreamWriter(new FileOutputStream(file, true))

public class IOTest {
	
	public static void write(File file) throws IOException {
		FileWriter fw = new FileWriter(file, true);

		// 要写入的字符串
		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
		fw.write(string);
		fw.close();
	}

	public static String read(File file) throws IOException {
		FileReader fr = new FileReader(file);
		// 一次性取多少个字节
		char[] chars = new char[1024];
		// 用来接收读取的字节数组
		StringBuilder sb = new StringBuilder();
		// 读取到的字节数组长度,为-1时表示没有数据
		int length;
		// 循环取数据
		while ((length = fr.read(chars)) != -1) {
			// 将读取的内容转换成字符串
			sb.append(chars, 0, length);
		}
		// 关闭流
		fr.close();

		return sb.toString();
	}
}
123456789101112131415161718192021222324252627282930

5、BufferedReader、BufferedWriter(字符缓冲流)

public class IOTest {
	
	public static void write(File file) throws IOException {
		// BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new
		// FileOutputStream(file, true), "UTF-8"));
		// FileWriter可以大幅度简化代码
		BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));

		// 要写入的字符串
		String string = "松下问童子,言师采药去。只在此山中,云深不知处。";
		bw.write(string);
		bw.close();
	}

	public static String read(File file) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(file));
		// 用来接收读取的字节数组
		StringBuilder sb = new StringBuilder();

		// 按行读数据
		String line;
		// 循环取数据
		while ((line = br.readLine()) != null) {
			// 将读取的内容转换成字符串
			sb.append(line);
		}
		// 关闭流
		br.close();

		return sb.toString();
	}
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mind_programmonkey

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值