精华内容
下载资源
问答
  • 1. 缓冲流 1.1 缓冲流的作用 使用缓冲数组以后,整体的读取,写入效率提升很大!!! 降低了CPU通过内存访问硬盘的次数。提高效率,降低磁盘损耗。 字节输入缓冲 BufferedInputStream 字节输出缓冲 ...
  • 【Java基础-3】吃透Java IO:字节流、字符流、缓冲流

    万次阅读 多人点赞 2020-09-23 20:12:33
    什么是Java-IO?字符流和字节流的区别与适用场景是什么?缓冲流到底实现了什么?如何高效地读写文件? 本文用大量的示例图和实例,带你吃透Java IO。

    前言

    有人曾问fastjson的作者(阿里技术专家高铁):“你开发fastjson,没得到什么好处,反而挨了骂背了锅,这种事情你为什么要做呢?”

    高铁答道:“因为热爱本身,就是奖励啊!”

    这个回答顿时触动了我。想想自己,又何尝不是如此。写作是个痛苦的过程,用心写作就更加煎熬,需字字斟酌,反复删改才有所成。然而,当一篇篇精良文章出自己手而呈现眼前时,那些痛苦煎熬就都那么值得。如果这些博文能有幸得大家阅读和认可,就更加是莫大的鼓舞了。技术人的快乐就是可以这么纯粹和简单。

    点波关注不迷路,一键三连好运连连!

    IO流是Java中的一个重要构成部分,也是我们经常打交道的。这篇关于Java IO的博文干货满满,堪称全网前三(请轻喷!)

    下面几个问题(问题还会继续补充),如果你能对答如流,那么恭喜你,IO知识掌握得很好,可以立即关闭文章。反之,你可以在后面得文章中寻找答案。

    1. Java IO流有什么特点?
    2. Java IO流分为几种类型?
    3. 字节流和字符流的关系与区别?
    4. 字符流是否使用了缓冲?
    5. 缓冲流的效率一定高吗?为什么?
    6. 缓冲流体现了Java中的哪种设计模式思想?
    7. 为什么要实现序列化?如何实现序列化?
    8. 序列化数据后,再次修改类文件,读取数据会出问题,如何解决呢?

    1 初识Java IO

    IO,即inout,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。

    Java 中是通过流处理IO 的,那么什么是流

    流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。

    当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

    一般来说关于流的特性有下面几点:

    1. 先进先出:最先写入输出流的数据最先被输入流读取到。
    2. 顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
    3. 只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

    1.1 IO流分类

    IO流主要的分类方式有以下3种:

    1. 按数据流的方向:输入流、输出流
    2. 按处理数据单位:字节流、字符流
    3. 按功能:节点流、处理流

    在这里插入图片描述

    1、输入流与输出流

    输入与输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流,这点很容易搞反。

    在这里插入图片描述
    2、字节流与字符流

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

    为什么要有字符流?

    Java中字符是采用Unicode标准,Unicode 编码中,一个英文字母或一个中文汉字为两个字节。
    在这里插入图片描述
    而在UTF-8编码中,一个中文字符是3个字节。例如下面图中,“云深不知处”5个中文对应的是15个字节:-28-70-111-26-73-79-28-72-115-25-97-91-27-92-124
    在这里插入图片描述

    那么问题来了,如果使用字节流处理中文,如果一次读写一个字符对应的字节数就不会有问题,一旦将一个字符对应的字节分裂开来,就会出现乱码了。为了更方便地处理中文这些字符,Java就推出了字符流。

    字节流和字符流的其他区别:

    1. 字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
    2. 字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。详见文末效率对比。

    以写文件为例,我们查看字符流的源码,发现确实有利用到缓冲区:
    在这里插入图片描述
    在这里插入图片描述

    3、节点流和处理流

    节点流:直接操作数据读写的流类,比如FileInputStream

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

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

    下图就很形象地描绘了节点流和处理流,处理流是对节点流的封装,最终的数据处理还是由节点流完成的。
    在这里插入图片描述
    在诸多处理流中,有一个非常重要,那就是缓冲流

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

    联想一下生活中的例子,我们搬砖的时候,一块一块地往车上装肯定是很低效的。我们可以使用一个小推车,先把砖装到小推车上,再把这小推车推到车前,把砖装到车上。这个例子中,小推车可以视为缓冲区,小推车的存在,减少了我们装车次数,从而提高了效率。
    在这里插入图片描述
    需要注意的是,缓冲流效率一定高吗?不一定,某些情形下,缓冲流效率反而更低,具体请见IO流效率对比。

    完整的IO分类图如下:
    在这里插入图片描述

    1.2 案例实操

    接下来,我们看看如何使用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();
    	}
    }
    

    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()
    	}
    }
    

    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();
    	}
    }
    

    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();
    	}
    }
    

    2 IO流对象

    第一节中,我们大致了解了IO,并完成了几个案例,但对IO还缺乏更详细的认知,那么接下来我们就对Java IO细细分解,梳理出完整的知识体系来。

    Java种提供了40多个类,我们只需要详细了解一下其中比较重要的就可以满足日常应用了。

    2.1 File类

    File类是用来操作文件的类,但它不能操作文件中的数据。

    public class File extends Object implements Serializable, Comparable<File>
    

    File类实现了SerializableComparable<File>,说明它是支持序列化和排序的。

    File类的构造方法

    方法名说明
    File(File parent, String child)根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
    File(String pathname)通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
    File(String parent, String child)根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
    File(URI uri)通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。

    File类的常用方法

    方法说明
    createNewFile()当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
    delete()删除此抽象路径名表示的文件或目录。
    exists()测试此抽象路径名表示的文件或目录是否存在。
    getAbsoluteFile()返回此抽象路径名的绝对路径名形式。
    getAbsolutePath()返回此抽象路径名的绝对路径名字符串。
    length()返回由此抽象路径名表示的文件的长度。
    mkdir()创建此抽象路径名指定的目录。

    File类使用实例

    public class FileTest {
    	public static void main(String[] args) throws IOException {
    		File file = new File("C:/Mu/fileTest.txt");
    
    		// 判断文件是否存在
    		if (!file.exists()) {
    			// 不存在则创建
    			file.createNewFile();
    		}
    		System.out.println("文件的绝对路径:" + file.getAbsolutePath());
    		System.out.println("文件的大小:" + file.length());
    
    		// 刪除文件
    		file.delete();
    	}
    }
    

    2.2 字节流

    InputStreamOutputStream是两个抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。

    InputStream为例,它继承了Object,实现了Closeable

    public abstract class InputStream
    extends Object
    implements Closeable
    

    InputStream类有很多的实现子类,下面列举了一些比较常用的:
    在这里插入图片描述
    详细说明一下上图中的类:

    1. InputStreamInputStream是所有字节输入流的抽象基类,前面说过抽象类不能被实例化,实际上是作为模板而存在的,为所有实现类定义了处理输入流的方法。
    2. FileInputSream:文件输入流,一个非常重要的字节输入流,用于对文件进行读取操作。
    3. PipedInputStream:管道字节输入流,能实现多线程间的管道通信。
    4. ByteArrayInputStream:字节数组输入流,从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去。
    5. FilterInputStream:装饰者类,具体的装饰者继承该类,这些类都是处理类,作用是对节点类进行封装,实现一些特殊功能。
    6. DataInputStream:数据输入流,它是用来装饰其它输入流,作用是“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。
    7. BufferedInputStream:缓冲流,对节点流进行装饰,内部会有一个缓存区,用来存放字节,每次都是将缓存区存满然后发送,而不是一个字节或两个字节这样发送,效率更高。
    8. ObjectInputStream:对象输入流,用来提供对基本数据或对象的持久存储。通俗点说,也就是能直接传输对象,通常应用在反序列化中。它也是一种处理流,构造器的入参是一个InputStream的实例对象。

    OutputStream类继承关系图:
    在这里插入图片描述

    OutputStream类继承关系与InputStream类似,需要注意的是PrintStream.

    2.3 字符流

    与字节流类似,字符流也有两个抽象基类,分别是ReaderWriter。其他的字符流实现类都是继承了这两个类。

    Reader为例,它的主要实现子类如下图:
    在这里插入图片描述
    各个类的详细说明:

    1. InputStreamReader:从字节流到字符流的桥梁(InputStreamReader构造器入参是FileInputStream的实例对象),它读取字节并使用指定的字符集将其解码为字符。它使用的字符集可以通过名称指定,也可以显式给定,或者可以接受平台的默认字符集。
    2. BufferedReader:从字符输入流中读取文本,设置一个缓冲区来提高效率。BufferedReader是对InputStreamReader的封装,前者构造器的入参就是后者的一个实例对象。
    3. FileReader:用于读取字符文件的便利类,new FileReader(File file)等同于new InputStreamReader(new FileInputStream(file, true),"UTF-8"),但FileReader不能指定字符编码和默认字节缓冲区大小。
    4. PipedReader :管道字符输入流。实现多线程间的管道通信。
    5. CharArrayReader:从Char数组中读取数据的介质流。
    6. StringReader :从String中读取数据的介质流。

    WriterReader结构类似,方向相反,不再赘述。唯一有区别的是,Writer的子类PrintWriter

    2.4 序列化

    待续…

    3 IO流方法

    3.1 字节流方法

    字节输入流InputStream主要方法:

    • read() :从此输入流中读取一个数据字节。
    • read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
    • read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
    • close():关闭此输入流并释放与该流关联的所有系统资源。

    字节输出流OutputStream主要方法:

    • write(byte[] b) :将 b.length 个字节从指定 byte 数组写入此文件输出流中。
    • write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
    • write(int b) :将指定字节写入此文件输出流。
    • close() :关闭此输入流并释放与该流关联的所有系统资源。

    3.2 字符流方法

    字符输入流Reader主要方法:

    • read():读取单个字符。
    • read(char[] cbuf) :将字符读入数组。
    • read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。
    • read(CharBuffer target) :试图将字符读入指定的字符缓冲区。
    • flush() :刷新该流的缓冲。
    • close() :关闭此流,但要先刷新它。

    字符输出流Writer主要方法:

    • write(char[] cbuf) :写入字符数组。
    • write(char[] cbuf, int off, int len) :写入字符数组的某一部分。
    • write(int c) :写入单个字符。
    • write(String str) :写入字符串。
    • write(String str, int off, int len) :写入字符串的某一部分。
    • flush() :刷新该流的缓冲。
    • close() :关闭此流,但要先刷新它。

    另外,字符缓冲流还有两个独特的方法:

    • BufferedWriternewLine()写入一个行分隔符。这个方法会自动适配所在系统的行分隔符。
    • BufferedReaderreadLine() :读取一个文本行。

    4 附加内容

    4.1 位、字节、字符

    字节(Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节等于八位。

    字符(Character)计算机中使用的字母、数字、字和符号,比如’A’、‘B’、’$’、’&'等。

    一般在英文状态下一个字母或字符占用一个字节,一个汉字用两个字节表示。

    字节与字符:

    • ASCII 码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。
    • UTF-8 编码中,一个英文字为一个字节,一个中文为三个字节。
    • Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
    • 符号:英文标点为一个字节,中文标点为两个字节。例如:英文句号 . 占1个字节的大小,中文句号 。占2个字节的大小。
    • UTF-16 编码中,一个英文字母字符或一个汉字字符存储都需要 2 个字节(Unicode 扩展区的一些汉字存储需要 4 个字节)。
    • UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。

    4.2 IO流效率对比

    首先,对比下普通字节流和缓冲字节流的效率:

    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		File file = new File("C:/Mu/test.txt");
    		StringBuilder sb = new StringBuilder();
    
    		for (int i = 0; i < 3000000; i++) {
    			sb.append("abcdefghigklmnopqrstuvwsyz");
    		}
    		byte[] bytes = sb.toString().getBytes();
    
    		long start = System.currentTimeMillis();
    		write(file, bytes);
    		long end = System.currentTimeMillis();
    
    		long start2 = System.currentTimeMillis();
    		bufferedWrite(file, bytes);
    		long end2 = System.currentTimeMillis();
    
    		System.out.println("普通字节流耗时:" + (end - start) + " ms");
    		System.out.println("缓冲字节流耗时:" + (end2 - start2) + " ms");
    
    	}
    
    	// 普通字节流
    	public static void write(File file, byte[] bytes) throws IOException {
    		OutputStream os = new FileOutputStream(file);
    		os.write(bytes);
    		os.close();
    	}
    
    	// 缓冲字节流
    	public static void bufferedWrite(File file, byte[] bytes) throws IOException {
    		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(file));
    		bo.write(bytes);
    		bo.close();
    	}
    }
    

    运行结果:

    普通字节流耗时:250 ms
    缓冲字节流耗时:268 ms
    

    这个结果让我大跌眼镜,不是说好缓冲流效率很高么?要知道为什么,只能去源码里找答案了。翻看字节缓冲流的write方法:

    public synchronized void write(byte b[], int off, int len) throws IOException {
        if (len >= buf.length) {
            /* If the request length exceeds the size of the output buffer,
               flush the output buffer and then write the data directly.
               In this way buffered streams will cascade harmlessly. */
            flushBuffer();
            out.write(b, off, len);
            return;
        }
        if (len > buf.length - count) {
            flushBuffer();
        }
        System.arraycopy(b, off, buf, count, len);
        count += len;
    }
    

    注释里说得很明白:如果请求长度超过输出缓冲区的大小,刷新输出缓冲区,然后直接写入数据。这样,缓冲流将无害地级联。

    但是,至于为什么这么设计,我没有想明白,有哪位明白的大佬可以留言指点一下。

    基于上面的情形,要想对比普通字节流和缓冲字节流的效率差距,就要避免直接读写较长的字符串,于是,设计了下面这个对比案例:用字节流和缓冲字节流分别复制文件。

    public class MyTest {
    	public static void main(String[] args) throws IOException {
    		File data = new File("C:/Mu/data.zip");
    		File a = new File("C:/Mu/a.zip");
    		File b = new File("C:/Mu/b.zip");
    
    		StringBuilder sb = new StringBuilder();
    
    		long start = System.currentTimeMillis();
    		copy(data, a);
    		long end = System.currentTimeMillis();
    
    		long start2 = System.currentTimeMillis();
    		bufferedCopy(data, b);
    		long end2 = System.currentTimeMillis();
    
    		System.out.println("普通字节流耗时:" + (end - start) + " ms");
    		System.out.println("缓冲字节流耗时:" + (end2 - start2) + " ms");
    	}
    
    	// 普通字节流
    	public static void copy(File in, File out) throws IOException {
    		// 封装数据源
    		InputStream is = new FileInputStream(in);
    		// 封装目的地
    		OutputStream os = new FileOutputStream(out);
    		
    		int by = 0;
    		while ((by = is.read()) != -1) {
    			os.write(by);
    		}
    		is.close();
    		os.close();
    	}
    
    	// 缓冲字节流
    	public static void bufferedCopy(File in, File out) throws IOException {
    		// 封装数据源
    		BufferedInputStream bi = new BufferedInputStream(new FileInputStream(in));
    		// 封装目的地
    		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(out));
    		
    		int by = 0;
    		while ((by = bi.read()) != -1) {
    			bo.write(by);
    		}
    		bo.close();
    		bi.close();
    	}
    }
    

    运行结果:

    普通字节流耗时:184867 ms
    缓冲字节流耗时:752 ms
    

    这次,普通字节流和缓冲字节流的效率差异就很明显了,达到了245倍。

    再看看字符流和缓冲字符流的效率对比:

    public class IOTest {
    	public static void main(String[] args) throws IOException {
    		// 数据准备
    		dataReady();
    
    		File data = new File("C:/Mu/data.txt");
    		File a = new File("C:/Mu/a.txt");
    		File b = new File("C:/Mu/b.txt");
    		File c = new File("C:/Mu/c.txt");
    
    		long start = System.currentTimeMillis();
    		copy(data, a);
    		long end = System.currentTimeMillis();
    
    		long start2 = System.currentTimeMillis();
    		copyChars(data, b);
    		long end2 = System.currentTimeMillis();
    
    		long start3 = System.currentTimeMillis();
    		bufferedCopy(data, c);
    		long end3 = System.currentTimeMillis();
    
    		System.out.println("普通字节流1耗时:" + (end - start) + " ms,文件大小:" + a.length() / 1024 + " kb");
    		System.out.println("普通字节流2耗时:" + (end2 - start2) + " ms,文件大小:" + b.length() / 1024 + " kb");
    		System.out.println("缓冲字节流耗时:" + (end3 - start3) + " ms,文件大小:" + c.length() / 1024 + " kb");
    	}
    
    	// 普通字符流不使用数组
    	public static void copy(File in, File out) throws IOException {
    		Reader reader = new FileReader(in);
    		Writer writer = new FileWriter(out);
    
    		int ch = 0;
    		while ((ch = reader.read()) != -1) {
    			writer.write((char) ch);
    		}
    		reader.close();
    		writer.close();
    	}
    
    	// 普通字符流使用字符流
    	public static void copyChars(File in, File out) throws IOException {
    		Reader reader = new FileReader(in);
    		Writer writer = new FileWriter(out);
    
    		char[] chs = new char[1024];
    		while ((reader.read(chs)) != -1) {
    			writer.write(chs);
    		}
    		reader.close();
    		writer.close();
    	}
    
    	// 缓冲字符流
    	public static void bufferedCopy(File in, File out) throws IOException {
    		BufferedReader br = new BufferedReader(new FileReader(in));
    		BufferedWriter bw = new BufferedWriter(new FileWriter(out));
    
    		String line = null;
    		while ((line = br.readLine()) != null) {
    			bw.write(line);
    			bw.newLine();
    			bw.flush();
    		}
    
    		// 释放资源
    		bw.close();
    		br.close();
    	}
    
    	// 数据准备
    	public static void dataReady() throws IOException {
    		StringBuilder sb = new StringBuilder();
    		for (int i = 0; i < 600000; i++) {
    			sb.append("abcdefghijklmnopqrstuvwxyz");
    		}
    		OutputStream os = new FileOutputStream(new File("C:/Mu/data.txt"));
    		os.write(sb.toString().getBytes());
    
    		os.close();
    		System.out.println("完毕");
    	}
    }
    

    运行结果:

    普通字符流1耗时:1337 ms,文件大小:15234 kb
    普通字符流2耗时:82 ms,文件大小:15235 kb
    缓冲字符流耗时:205 ms,文件大小:15234 kb
    

    测试多次,结果差不多,可见字符缓冲流效率上并没有明显提高,我们更多的是要使用它的readLine()newLine()方法。

    4.3 NIO

    待续…

    展开全文
  • 本文主要介绍了java的IO流中的缓冲流的使用,缓冲流分为字节和字符缓冲流。分享了有关它们的实例代码,具有一定的参考价值,下面跟着小编一起来看下吧
  • 主要介绍了Java IO流之字符缓冲流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • JavaIO实例,包括:字节流、字符流、缓冲流、转换流
  • 主要为大家详细介绍了java使用缓冲流复制文件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了Java字节缓冲流原理与用法,结合实例形式总结分析了java字节流与缓冲区相关原理与操作技巧,需要的朋友可以参考下
  • 缓冲流

    千次阅读 2019-06-14 10:06:37
    缓冲流的原理 java.io.BufferedOutputStream extends OutputStream BufferedOutputStream ————字节缓冲输出流 继承自父类的共性方法 public void close()——关闭此输出流并释放与此流相关联的任何系统资源...

    缓冲流的原理

    在这里插入图片描述
    java.io.BufferedOutputStream extends OutputStream

    BufferedOutputStream ————字节缓冲输出流

    继承自父类的共性方法

    • public void close()——关闭此输出流并释放与此流相关联的任何系统资源。
    • public void flush()——刷新此输出流并强制任何缓冲的输出字节被写出。
    • public void write(byte[ ] b)——将b.length字节从指定的字节数组写入到此输出流。
    • public void write(byte[ ] b,int off,int len)——从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
    • public abstract void write(int b)——将指定的字节输出流。
      构造方法
    • BufferedOutputStream (OutputStream out)——创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
    • BufferedOutputStream (OutputStream out,int
      size)——创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
      参数
    • OutputStream out————字节输出流
      我们可以传递FileOutPutStream,缓冲流会给FileOutPutStream增加一个缓冲区,提高FileOutPutStream的写入效率。
    • int size—————————指定缓冲流内部缓冲区的大小,不指定默认。
      使用步骤(重点)
      1.创建FileOutPutStream对象,构造方法中绑定要输出的目的地。
      2.创建BufferedOutputStream对象,构造方法中传递FileOutPutStream对象,提高FileOutPutStream对象效率。
      3.使用BufferedOutputStream对象中的方法write,把数
      据写入到内部缓冲区中。
      4.使用BufferedOutputStream对象中的方法flush,把内部缓冲区中的数据,刷新到文件中。
      5.释放资源(会先调用flush方法刷新数据,第四步可以省略)。

    java.io.BufferedIutputStream extends IutputStream

    BufferedIntputStream ————字节缓冲输入流

    继承自父类的共性方法

    • int read()——从输入流中读取数据的下一个字节。
    • int read(char[ ] cbuf)——从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。
    • void close()——关闭此输入流并释放与此流相关联的任何系统资源。
    • 构造方法
    • BufferedIntputStream (IutputStream in)——创建一个BufferedIntputStream 并保存其参数,即输入流in,以便将来使用。
    • BufferedIntputStream (IntputStream in,int
      size)——创建具有指定缓冲区大小的BufferedIntputStream 保存其参数,即输入流in。
      参数
    • IntputStream in————字节输入流
      我们可以传递FileIntPutStream,缓冲流会给FileIntPutStream增加一个缓冲区,提高FileIntPutStream的读取效率。
    • int size—————————指定缓冲流内部缓冲区的大小,不指定默认。
      使用步骤(重点)
      1.创建FileIntPutStream对象,构造方法中绑定要读取的数据。
      2.创建BufferedIntputStream 对象,构造方法中传递FileIntPutStream对象,提高FileIntPutStream对象读取效率。
      3.使用BufferedIntputStream 对象中的方法read,读取文件
      4.释放资源。

    java.io.BufferedWriter extends Writer

    字符缓冲输出流——BufferedWriter类

    继承自父类的共性成员方法

    • public void write(int c)—————写入单个字符。

    • public void write(char[ ] cbuf)——写入字符数组。

    • abstract void write(char[ ] cbuf,int off,int len)——写入字符数组的某一部分,off数组的开始索引,len写的字符个数。

    • void write(String str)——写入字符串。

    • void write(char[ ] cbuf,int off,int len)——写入字符数组的某一部分,off字符串的开始索引,len写的字符个数。

    • void flush()——刷新该流的缓冲。

    • public void close()————————关闭此流,但要先刷新它。
      构造方法

    • BufferedWriter (Writer out)————创建一个使用默认大小输出缓冲区的缓冲字符输出流。

    • BufferedWriter (Writer out,int sz)——创建一个使用给定大小输出缓冲区的缓冲字符输出流。
      参数
      Writer out————字符输出流
      我们可以传递FileWtite,缓冲流会给FileWtite增加一个缓冲区,提高FileWtite的写入效率。
      int sz—————指定缓冲区的大小,不写默认大小。
      特有的成员方法

    • void newLine()————写入一个行分隔符。会根据不同的操作系统,获取不同的行分隔符。

    使用步骤
    1.创建字符缓冲输出流对象,构造方法中传递字符输出流。
    2.调用字符缓冲输出流对象的方法write,把数据写入到缓冲区中。
    3.调用字符缓冲输出流对象的方法flush,把内存缓冲区中的数据,刷新到文件中。
    4.释放资源。
    java.io.BufferedReader extends Reader

    字符输入流——BufferedReader 类

    继承自父类的共性成员方法

    • int read()——读取单个字符并返回。
    • int read(char[ ] cbuf)——一次读取多个字符,将字符读入数组。
    • void close()——关闭该流并释放与之关联的所有资源。
      构造方法
    • BufferedReader (Reader in)————创建一个使用默认大小的输入缓冲区的缓冲字符输入流。
    • BufferedReader (Reader in)————创建一个使用是定大小输入缓冲区的缓冲字符输入流。
      参数——————读取文件的数据源
      Reader in——字符输入流
      我们可以传递FileReader,缓冲流会给FileReader增加一个缓冲区,提高FileReader的读取效率。
      特有的成员方法
    • String readLine( )——————读取一个文本行。读取一行数据。
      行的终止符号—————————通过下列字符即可认为某行已终止————换行(‘\n’)、回车(‘\r’)或者回车后直接跟着换行(\n\r)。
      返回值
      包含改行内容的字符串,不包含任何终止符,如果已达流末尾,则放回null。
      使用步骤
      1.创建一个字符缓冲输入流对象,构造方法中传递符缓冲输入流。
      2.使用符缓冲输入流对象中的方法read/readLine读取文本。
      3.释放资源。

    练习——对文本的内容进行排序

    package cn.lrf.IODemo;
    
    import java.io.*;
    import java.util.HashMap;
    
    /*练习
     * 对文本的内容进行排序
     * 按照(1,2,3...顺序进行排序)
     * 分析
     * 1.创建一个HashMap集合对象,可以存储每行文本的序号1,2,3...);value:存储每行的文本
     * 2.创建字符缓冲输入流对象,构造方法中绑定字符输入流。
     * 3.创建字符缓冲输出流对象,构造方法中绑定字符输入流。
     * 4.使用字符缓冲输入流中的方法readLine,逐行读取文本。
     * 5.对读取到的文本进行切割,获取行中的序号和文本内容。
     * 6.把切割好的序号和文本的内容存储到HashMap集合中(key序号是有序的,会自动排序1,2,3,4...)
     * 7.遍历HashMap集合,获取每一个键值对。
     * 8.把每一个键值对,拼接为一个文本行
     * 9.把拼接好的文本,使用字符缓冲输出流的方法write,写入到文件中。
     * 10.释放资源。
     * */
    public class Demo05Test {
        public static void main(String[] args) throws IOException {
            // 1.创建一个HashMap集合对象,可以存储每行文本的序号1,2,3...);value:存储每行的文本
            HashMap<String, String> map = new HashMap<>();
            // 2.创建字符缓冲输入流对象,构造方法中绑定字符输入流。
            BufferedReader br = new BufferedReader(new FileReader("day08-code\\src\\cn\\lrf\\IODemo\\c.txt"));
            //3.创建字符缓冲输出流对象,构造方法中绑定字符输入流。
            BufferedWriter bw = new BufferedWriter(new FileWriter("day08-code\\src\\cn\\lrf\\IODemo\\d.txt"));
            // 4.使用字符缓冲输入流中的方法readLine,逐行读取文本。
            String line;
            while ((line = br.readLine()) != null) {
                // 5.对读取到的文本进行切割,获取行中的序号和文本内容。
                String[] arr = line.split("\\.");
                //6.把切割好的序号和文本的内容存储到HashMap集合中(key序号是有序的,会自动排序1,2,3,4...)
                map.put(arr[0], arr[1]);
            }
            // 7.遍历HashMap集合,获取每一个键值对。
            for (String key : map.keySet()) {
                String value = map.get(key);
                // 8.把每一个键值对,拼接为一个文本行
                line = key + "." + value;
                // 9.把拼接好的文本,使用字符缓冲输出流的方法write,写入到文件中。
                bw.write(line);
                bw.newLine();//写换行
            }
            // 10.释放资源。
    
            bw.close();
    
            br.close();
        }
    }
    
    
    展开全文
  • IO流之缓冲流

    2020-12-22 11:47:01
    1.1 缓冲流有什么作用 使用缓冲数组以后,整体的读取,写入效率提升很大,降低了CPU通过内存访问硬盘的次数,提高效率,降低磁盘损耗 字节输入缓冲 BufferedInputStream 字节输出缓冲 BufferedOutputStream 字符输入...
  • 处理流|缓冲流(Buffered)

    千次阅读 2020-03-21 12:17:53
    文章目录缓冲流(字节型)实现非文本的复制缓冲流(字符型)实现文本的复制节点流与缓冲流总结缓冲流练习1缓冲流练习2 缓冲流(字节型)实现非文本的复制 Buffered能够提高读写速度的原因:内部提供了一个缓冲区。 打开...


    缓冲流(字节型)实现非文本的复制

    • Buffered能够提高读写速度的原因:内部提供了一个缓冲区。
      打开源码,可以发现其内部提供了一个大小为1024八倍的常量,相当于提供了一个8192大小的缓冲区。当读文件时,先把文件读进缓冲区中,当达到8192大小时一次性写出。相应的也有一个flush()方法用来刷新缓冲区。(缓冲流的write中会自动进行flush刷新。)
      -

    使用字节型缓冲流实现非文本文件(.MP4)的复制:

        @Test
        public void testCopyFile() {
            long start = System.currentTimeMillis();
            String srcPath = "video.mp4";
            String destPath = "video3.mp4";
            copyFileWithBuffered(srcPath, destPath);
            long end = System.currentTimeMillis();
            System.out.println("缓冲流(Buffered)复制文件花费的时间为:" + (end - start));
        }
    
        public void copyFileWithBuffered(String srcPath, String destPath) {
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            try {
                bis = new BufferedInputStream(new FileInputStream(new File(srcPath)));
                bos = new BufferedOutputStream(new FileOutputStream(new File(destPath)));
                //3.读写操作
                byte[] buffer = new byte[1024];
                int len;
                while ((len = bis.read(buffer)) != -1) {
                    bos.write(buffer, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭外层流的同时,内层流也会自动进行关闭;可以省略内层流的关闭.
                if (bos != null) {
                    try {
                        bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    缓冲流(字符型)实现文本的复制

        @Test
        public void testBufferedReaderBufferedWriter(){
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                br = new BufferedReader(new FileReader(new File("hello.txt")));
                bw = new BufferedWriter(new FileWriter(new File("hello2.txt")));
                //方式一:
    //            char[] cbuf = new char[1024];
    //            int len;
    //            while ((len = br.read(cbuf)) != -1) {
    //                bw.write(cbuf, 0, len);
    //            }
                //方式二:
                String data;
                while((data=br.readLine())!=null){
                    bw.write(data);
                    bw.newLine();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭外层流的同时,内层流也会自动进行关闭;可以省略内层流的关闭.
                if (bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    节点流与缓冲流总结

    节点流(又称文件流)缓冲流(处理流的一种)
    FileInputStream (read(byte[] buffer))BufferedInputStream (read(byte[] buffer))
    FileOutputStream (write(byte[] buffer,0,len))BufferedOutputStream (write(byte[] buffer,0,len))
    FileReader (read(char[] cbuf))BufferedReader (read(char[] cbuf)/readLine())
    FileWriter (write(char[] cbuf,0,len))BufferedWriter(write(char[] cbuf,0,len)/flush())

    缓冲流练习1

    需求:使用缓冲流实现图片加密解密操作。

    异或加密:与其说这是一种加密算法,倒不如称其为文件信息的简单变换,将每一个数据与某给定数据进行异或操作即可完成加密或解密。

    图片加密:

      @Test
        public void test1(){
            BufferedInputStream fis = null;
            BufferedOutputStream fos = null;
            try {
                fis = new BufferedInputStream(new FileInputStream("img1.jpg"));
                fos = new BufferedOutputStream(new FileOutputStream("img2.jpg"));
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) != -1) {
                    for (int i = 0; i < len; i++) {
                        buffer[i] = (byte) (buffer[i]^5);
                    }
                    fos.write(buffer,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(fis!=null){
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    图片解密:

      @Test
        public void test2(){
            BufferedInputStream fis = null;
            BufferedOutputStream fos = null;
            try {
                fis = new BufferedInputStream(new FileInputStream("img2.jpg"));
                fos = new BufferedOutputStream(new FileOutputStream("img3.jpg"));
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) != -1) {
                    for (int i = 0; i < len; i++) {
                        buffer[i] = (byte) (buffer[i]^5);
                    }
                    fos.write(buffer,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(fis!=null){
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    缓冲流练习2

    获取文本上每个字符出现的次数。(提示:遍历文本的每一个字符,字符以及出现的次数保存在Map中;将Map中数据写入文件。)

     @Test
        public void test3(){
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                Map<Character, Integer> map = new HashMap<>();
                br = new BufferedReader(new FileReader("hello.txt"));
                bw = new BufferedWriter(new FileWriter("copyHello.txt"));
                int c = 0;
                while ((c = br.read()) != -1) {
                    char ch = (char) c;
                    if (map.get(ch) == null) {
                        map.put(ch, 1);
                    } else {
                        map.put(ch, map.get(ch) + 1);
                    }
                }
                Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
                for (Map.Entry<Character, Integer> i : entrySet) {
                    switch (i.getKey()) {
                        case ' ':
                            bw.write("空格:" + i.getValue());
                            break;
                        case '\t':
                            bw.write("tab:" + i.getValue());
                            break;
                        case '\r':
                            bw.write("回车:" + i.getValue());
                            break;
                        case '\n':
                            bw.write("换行:" + i.getValue());
                            break;
                        default:
                            bw.write(i.getKey() + "=" + i.getValue());
                            break;
                    }
                    bw.newLine();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    在这里插入图片描述
    程序执行后,写出到新文件中的内容如下:
    在这里插入图片描述

    展开全文
  • 目录java IO流学习笔记——(3)字节缓冲流&字符缓冲流&转换流&数据流字节缓冲流 —BufferedInputStream&BufferedOutputStream字符缓冲流—BufferedReader&BufferedWriter转换流—InputStreamReader&...
  • java虚拟内存和缓冲流

    2018-08-06 21:51:37
    虚拟内存和缓冲流,直接粘贴到eclipse或者cmd运行即可
  • 1.什么是缓冲流,有什么作用? 这里需要说明一点小知识,在对硬盘进行读写操作时,一个完整的文件的读写速率要远远高于同样大小的散文件的读写速率。这是因为散文件需要不断地访问、关闭硬盘,极大地浪费了时间,...
  • 面向对象程序设计 FIle I/O;使用缓冲流写文本文件;BufferedWriter继承于Writer类该类带有缓冲区可以先把一批数据写到缓冲区当缓冲区满的时候再把缓冲区的数据写字符输出流中这样避免每次都执行物理操作提高输出效果;
  • Java学习日志(二十一)缓冲流原理字节缓冲输出流:BufferedOutputStream字节缓冲输入流:BufferedInputStream字符缓冲输出流:BufferedWriter字符缓冲输入流:BufferedReader文件复制文件排序转换流原理字符转换...
  • io流中普通流(字节流)和缓冲流的通俗理解

    千次阅读 多人点赞 2020-07-30 15:31:41
    字节流和缓冲流 字节流:数据是以字节为单位进行读写操作 程序直接从硬件中读物或写入数据,一切文件在系统中都是以字节的形式保存的,无论你是文档文件、视频文件、音频文件…,需要读取这些文件都可以用...

    字节流和缓冲流

    • 字节流:数据是以字节为单位进行读写操作
      程序直接从硬件中读物或写入数据,一切文件在系统中都是以字节的形式保存的,无论你是文档文件、视频文件、音频文件…,需要读取这些文件都可以用FileInputStream去读取其保存在存储介质(磁盘等)上的字节序列,文件字节输入流的读取时,是直接同字节流中读取的。由于字节流是与硬件(存储介质)进行的读取,所以速度较慢。而CPU需要使用数据时通过read()、read(byte[])读取数据时就要受到硬件IO的慢速度限制。

    • 缓冲流:将一个一个的字节先存入到缓冲区中
      在JVM中会开辟一块缓冲区的内存空间,然后将文件中的数据读取到缓冲区中,直到读满这个缓冲,才会将缓冲区中的数据获取到程序中。
      在JVM中会开辟一块缓冲区的内存空间,然后将程序中的数据写入到缓冲区中,直到写满这个缓冲,才会将缓冲区中的数据写入到文件中。

    • 原理总结
      带缓冲的字节输入流:上面我们知道文件字节输入流的读取时,是直接同字节流中读取的。由于字节流是与硬件(存储介质)进行的读取,所以速度较慢。而CPU需要使用数据时通过read()、read(byte[])读取数据时就要受到硬件IO的慢速度限制。我们又知道,CPU与内存发生的读写速度比硬件IO快10倍不止,所以优化读写的思路就有了:在内存中建立缓存区,先把存储介质中的字节读取到缓存区中。CPU需要数据时直接从缓冲区读就行了,缓冲区要足够大,在被读完后又触发fill()函数自动从存储介质的文件字节内容中读取字节存储到缓冲区数组。
      BufferedInputStream 内部有一个缓冲区,默认大小为8M,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源 (譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容返回给用户.由于从缓冲区里读取数据远比直接从存储介质读取速度快,所以BufferedInputStream的效率很高。
      **

    • 字节流

    **
    字节流

    • 缓冲流
      缓冲流
      通俗的来讲,缓冲输出流相当于先把文件写入JVM中的缓冲区,缓冲区满后缓冲区再写入硬盘,乍听起来和字节流一个数组一个数组写入有点像,那我这么来说,我们程序相当于菜农,要卖菜给超市,字节流是自己开车运到超市,缓冲流是先卖给收购商,收购商运到超市,如图:
      示例
      在这里插入图片描述
    • 方式1相当于菜农一棵菜一棵菜运到超市,这种速率最慢;
    • 方式2相当于菜农一次运一小车菜到超市,这种速率适中;
    • 方式3相当于菜农一棵菜一棵菜运到收购商,收购商再大车运到超市,这种速率适中;
    • 方式4相当于菜农小车运给收购商,收购商大车运到超市,因为收购商和超市交易速度要大于菜农和超市交易速度,这种速率最快。
      可以看出方式字节流以数组形式写数据和缓冲流以字节写数据有点类似,速度因数组大小(运菜车大小)的影响两种方式速度差别不大,其中缓冲流以数组形式写数据最快。
      输入流可反之思考;

    注:以上自己理解,运菜情节需要,请勿较真哈。

    展开全文
  • 缓冲流:BufferedInputStream、BufferedOuputStream、BufferedReader、BufferedWriter 目的:通过使用缓存,加快读取和写入数据的速度。 缓冲流是一种包装流。 示例代码: public class TestBufferedStream { ...
  • 缓冲流详细解释

    千次阅读 2019-04-02 11:19:00
    缓冲流: 概述:缓冲流,也叫高效流,是对4个基本的FileXxx流的增强,所以也是4个流,按照数据类型分类: 字节流顶层父类:InputStream(字节输入流) 和 OutputStream(字节输出流) 字符流顶层父类:Reader(字符输入流) 和 ...
  • 缓冲流、转换流、序列化流 主要内容 缓冲流 转换流 序列化流 打印流 目标 能够使用字节缓冲流读取数据到程序 能够使用字节缓冲流写出数据到文件 能够明确字符缓冲流的作用和基本用法 能够使用缓冲流的特殊...
  • Java利用缓冲流读写文件

    千次阅读 2019-10-26 16:11:23
    从控制台读取数据写入文件 读取文件输出到控制台 public class BookTest { public static void main(String[] args) { //从控制台输入信息并写入文件中 BufferedReader ir=new ... //包装成字符输入缓冲流...
  • 缓冲流的优缺点

    千次阅读 2019-11-26 09:18:48
    不带缓冲读取到一个字节或字符,就直接写出数据 带缓冲读取到一个字节或字符,先不输出,等达到了缓冲区的最大容量再一次性写出去 优点:减少了写出次数,提高了效率 缺点:接收端可能无法及时获取到...
  • 使用缓冲流读取文本文件;BufferedReader继承于Reader类该类带有缓冲区可以先把一批数据读到缓冲区并且提供了特有的readline)方法实现读取一个文本行的功能从而提高读取操作效率 常用构造方法如下;
  • Java 缓冲流简介及简单用法

    千次阅读 2018-03-29 17:05:18
    在java编程中, 我们有时会听到缓冲流和原始流等字眼. 其实在之前的博文中, 提到过流可以分为原始流和处理流. http://blog.csdn.net/nvd11/article/details/30126233 也就是说处理流是包裹在原始流...
  • //对字符流的封装,比字符流更高级的缓冲流,一次可以读取或写入一行字符 } } Java中的IO流是输入输出流。至于理解,可以将输入和输出两个端点看作是两个工厂,工厂之间需要互相运输货物,而流则是两工厂之间的...
  • 什么是字节缓冲流

    千次阅读 2020-08-21 16:27:48
    BufferInputStream:创建一个内部缓冲区数组,当从内读取和 跳过字节时,内部缓冲区根据需要从包含的输入流重新填充,一次多个字节。 BufferOutputStream:缓冲输出流。程序向底层输出流写字节,...字节缓冲流:提供的是.
  • java 缓冲流+原理图解

    千次阅读 2020-07-19 13:49:45
    java 缓冲流 什么是java缓冲流缓冲流也叫高效流,是对四个基本的FileXxx流的增强,按照数据类型分类: 字节缓冲流 :BufferedInputStream,BufferedOutputStream 字符缓冲流:BufferedReader,BufferedWriter ...
  • 缓冲流学习及理解关于缓冲流的理解缓冲流与字节流读写时使用字节数组关于缓冲区以及缓冲区刷新文件复制中缓冲流的效果总结 关于缓冲流的理解 缓冲流这个概念是针对底层流来说的,属于高层次的流,在平常的底层流...
  • //创建读缓冲流 BufferedWriter bw = new BufferedWriter(new FileWriter(f2)); //创建写缓冲流 //一行一行写入 String line = null; while ((line = br.readLine()) != null) { bw.flush(); bw.write(line...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 366,982
精华内容 146,792
关键字:

缓冲流