一. 缓冲流

​ 缓冲流是处理流的一种,也叫高效流,是对4个基本输入输出流的增强,它让输入输出流具有1个缓冲区,能显著减小与外部的IO次数,从而提高读写的效率,并且提供了一些额外的读写方法。

​ 因为是对4个基本输入输出流的增强,因此缓冲流也有4个,分为字节缓冲流和字符缓冲流。

  • 字节缓冲流:BufferedInputStream 和 BufferedOutputStream
  • 字符缓冲流:BufferedReader 和 BufferedWriter

1.字节缓冲流

构造方法:

  • BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
  • BufferedInputStream(InputStream in):创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

常用方法:

​ 字节缓冲流常用方法基本与字节流的方法一样。

示例:通过复制大文件测试缓冲流的效率

使用基本流:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; public class TestBuffered {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("File\\new.tar.gz");
FileInputStream fis = new FileInputStream("test.tar.gz"); int len;
byte[] bytes = new byte[1024]; long start = System.currentTimeMillis(); while((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
System.out.println("使用时间:" + (System.currentTimeMillis() - start) + "毫秒"); fos.close();
fis.close();
}
}

耗时:36719毫秒

使用缓冲流:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException; public class TestBuffered {
public static void main(String[] args) throws IOException {
// FileOutputStream fos = new FileOutputStream("File\\new.tar.gz");
// FileInputStream fis = new FileInputStream("test.tar.gz");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("File\\new.tar.gz"));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.tar.gz")); int len;
byte[] bytes = new byte[1024]; long start = System.currentTimeMillis(); while((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
System.out.println("使用时间:" + (System.currentTimeMillis() - start) + "毫秒"); bos.close();
bis.close();
}
}

耗时:26595毫秒

2. 字符缓冲流

构造方法:

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

常用方法:

​ 字符缓冲流的基本方法与普通字符流基本一致。

特有方法:

​ 字符缓冲流新有的方法:

  • BufferedWritervoid newLine() 写入一个行分隔符。根据系统属性定义换行符
  • BufferedReaderString readLine() 读取一个文本行。每次读取一行

示例:void newLine()

import java.io.*;
import java.io.IOException; public class TestBuffered {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("File\\b.txt")); bw.write("你好");
bw.newLine(); // 换行 bw.write("我是中国人");
bw.newLine(); // 换行 bw.close();
}
}

示例:String readLine()

import java.io.*;
import java.io.IOException; public class TestBuffered {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("File\\a.txt")); String line; while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}

注意:

readLine()读取到末尾后再读取,返回的是null,不再是-1了。

二.转换流

​ 讲到转换流之前,涉及到一个编码与解码的问题,一般来说,使用规则A编码,则需要使用A规则解码才可以正常显示文本符号,而在Java中不同的编码方式,中文所占的字节数不同,所以当使用不同编码时,需要对应的编码方式的解码才能正常显示中文,否则将会导致乱码的现象。比如使用GBK编码,却用UTF-8解码,将会变成乱码。

​ 讲到编码就会提到一个叫字符集的东西,字符集也叫编码表,是一个系统支持的所有字符的集合。常见的字符集有:ASCII,GBK,Unicode等。

编码相关介绍可参考:

深入分析 Java 中的中文编码问题

总之涉及到中文,今后编码格式统一都为:UTF-8

为了解决存在的乱码问题,我们需要将字节流转成字符流 或字符流转成字节流,并指定编码格式。

Java提供了两个转换流:OutputStreamWriterInputStreamReader

1. OutputStreamWriter转换流

OutputStreamWriter是Writer的子类,是字符流通向字节流的桥梁,可以使用指定的charset将要写入流的字符编码成字节。它的字符集可以显示指定,否则将使用平台默认的字符集。

构造方法:

  • OutputStreamWriter(OutputStream out):创建使用默认字符编码的 OutputStreamWriter。
  • OutputStreamWriter(OutputStream out, String charsetName):创建使用指定字符集的 OutputStreamWriter。

示例:指定编码写文件

import java.io.*;

public class TestOutputStreamWriter {
public static void main(String[] args) throws IOException{
// 指定UTF-8的编码格式,写入
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("File\\d.txt"),"utf-8"); osw.write("中国");
osw.close();
}
}

打开文件d.txt,如下图:

import java.io.*;

public class TestOutputStreamWriter {
public static void main(String[] args) throws IOException{
// 指定GBK的编码格式,写入
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("File\\d.txt"),"GBK");
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("File\\d.txt")); osw.write("中国");
osw.close();
}
}

打开文件d.txt,如下图

说明:

​ 程序是在Windows下编译运行的,Windows默认编码集为GBK,所以当代码指定UTF-8编码写入文件时候,Windows下打开的是乱码;而当指定GBK编码,或者使用系统默认编码时候,Windows打开时候是正常显示的。

​ 所以,在开发中,以何种编码写入,就必须要以同种编码读取,否则会产生乱码。

2.InputStreamReader转换流

InputStreamReader是Reader的子类,是字节流通向字符流的桥梁,可以使用指定的charset读取字节并将其解码为字符。它的字符集可以显示指定,否则将使用平台默认的字符集。

构造方法:

  • InputStreamReader(InputStream in):创建一个使用默认字符集的 InputStreamReader。
  • InputStreamReader(InputStream in ,String charsetName):创建使用指定字符集的 InputStreamReader。

示例:指定编码读取文件

import java.io.*;

public class TestInputStreamReader {
public static void main(String[] args) throws IOException {
// 文件c.txt内容为:你好,编码为:UTF-8
InputStreamReader isr = new InputStreamReader(new FileInputStream("File\\c.txt"),"UTF-8");
int r; while((r = isr.read()) != -1) {
System.out.print((char)r);
}
isr.close(); System.out.println("=================="); InputStreamReader isr1 = new InputStreamReader(new FileInputStream("File\\c.txt"),"GBK");
int r1; while((r1 = isr1.read()) != -1) {
System.out.print((char)r1); // 浣犲ソ
}
isr1.close();
}
}

同理,当保存的文件的编码时UTF-8时候,只有使用UTF-8的编码去读取文件才能得到正常的显示。

3. 转换流理解图

图片出处:

说明:

磁盘文件是以字节的方式存储的,内存中的程序时以字符存储的。

所以当写文件到磁盘中时,需要先将程序中的数据(字符)使用OutputStreamWriter转换为字节,在写入文件(因此OutputStreamWriter就是字符到字节的桥梁)

当从磁盘中读取文件时,文件是以字节的方式存储的,所以需要先将字节使用InputStreamReader转换为字符,再读取到内存的程序中。(因此InputStreamReader就是字节到字符的桥梁)

Java IO---缓冲流和转换流的更多相关文章

  1. 我爱Java系列之《JavaEE学习笔记day12》---【缓冲流、转换流、序列/反序列化流、打印流】

    [缓冲流.转换流.序列/反序列化流.打印流] 一.缓冲流 1.字节缓冲输出流 java.io.BufferedOutputStream extends OutputStream 高效字节输出流 写入文 ...

  2. 01 语言基础+高级:1-8 File类与IO流_day10【缓冲流、转换流、序列化流】

    day10[缓冲流.转换流.序列化流] 主要内容 缓冲流 转换流 序列化流 打印流 教学目标 能够使用字节缓冲流读取数据到程序 能够使用字节缓冲流写出数据到文件 能够明确字符缓冲流的作用和基本用法 能 ...

  3. Java IO流之转换流

    一.转换流 1.在IO包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流-字符流的转换流 2.转换流用于在字节流和字符流之间转换 3.转换流本身是字符流 二.两种转换流 Ou ...

  4. java ->IO流_转换流

    转换流 在学习字符流(FileReader.FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputStre ...

  5. 10缓冲流、转换流、序列化流、Files

    十.流 10.1 缓冲流 10.1.1 概述                 缓冲流是对4个基本的FileXxx流的增强,所以也是4个流,按照数据类型进行分类                     ...

  6. javaSE学习笔记(15) ---缓冲流、转换流、序列化流

    javaSE学习笔记(15) ---缓冲流.转换流.序列化流 缓冲流 昨天复习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流.比如能够高效读写的缓冲流,能够转换编码的转换流,能够持久化 ...

  7. 383 day10缓冲流、转换流、序列化流

    day10[缓冲流.转换流.序列化流] 主要内容 缓冲流 转换流 序列化流 打印流 教学目标 [ ] 能够使用字节缓冲流读取数据到程序 [ ] 能够使用字节缓冲流写出数据到文件 [ ] 能够明确字符缓 ...

  8. Java IO(Properties/对象序列化/打印流/commons-io)

    Java IO(Properties/对象序列化/打印流/commons-io) Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载. ...

  9. IO流之转换流

    转换流 OutputStreamWriter类 查阅OutputStreamWriter的API介绍,OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流 ...

随机推荐

  1. 数据结构 - 链栈的实现 C++

    链栈封装 C++ 使用C++对链栈进行了简单的封装,实现了栈的基本操作 封装方法: pop(),top(),size(),empty(),push() 代码已经过测试 #pragma once #in ...

  2. nginx 设置反向代理

    一.多个路径指向同一ip的不同服务 参考地址:https://www.cnblogs.com/hanmk/p/9289069.html 编辑nginx.conf配置文件,新增加一个server模块,或 ...

  3. 安装Vyos

      Vyos是一个开源的网络操作系统,基于Debian,相对于ROS需要购买license,Vyos就更加开放的多. 下载Vyos wget http://vyos.hecint.com/iso/re ...

  4. Jmeter函数助手—自带方法

    1.${__time()}---->当前时间,一串数字格式 2.${__time(yyyy-MM-dd)}----->当前日期,年-月-日格式 3.${__time(yyyy-MM-dd ...

  5. zabbix-钉钉报警媒介

    (1)第三方报警平台(钉钉) 先指定要发送的群,在群里创建机器人 添加机器人 可以参考   “说明文档” 创建测试文档 vim   ceshi.sh curl 'https://oapi.dingta ...

  6. ESA2GJK1DH1K基础篇: Android实现SmartConfig简单Demo

    下载源码去 百度安信可 导入源码 等待加载完 我的提示更新下软件 ,我就更新下 安装完成以后重新导入工程 安装到手机 注意,由于Android 9.0 以后的获取WIFI名称需要打开GPS,所以如果提 ...

  7. 在pat考试中快速调整Dev-cpp颜色配置

    在菜单栏中:tool(工具)->Edit Options(编辑器环境) 点击General选项卡: 把Color调为黑色. 点击Color选项卡: 讲Select theme设置为Obsidia ...

  8. Codeforces Round 558(Div 2)题解

    这场比赛没有打,后来和同学们一起开了场镜像打…… B是SB题结果WA了5发…… C是SB题结果差5min调出……虽然中间有个老师讲题吃掉了1h D是比较神仙的题(2200),但是做出来了?算是比较超常 ...

  9. PatchMatch小详解

    最近发了两片patch match的,其实自己也是有一些一知半解的,找了一篇不知道谁的大论文看了看,又回顾了一下,下面贴我的笔记. The PatchMatch Algorithm patchmatc ...

  10. LongAdder源码分析

    AtomicLong是作用是对长整形进行原子操作,显而易见,在java1.8中新加入了一个新的原子类LongAdder,该类也可以保证Long类型操作的原子性,相对于AtomicLong,LongAd ...