[Java学习笔记]IO流——字节流和字符流

字节流

抽象超类:

  • InputStream是所有字节输入流的父类,其定义了基础的读取方法,常用的方法如下:
    — int read() 读取一个字节,以int形式返回(取一个byte也即“低8位”),
    若返回值为-1,则表示EOF(End Of File)
    — int read(byte[] d) 尝试读取给指定数组的length个字节并存入该数组,
    返回值为实际读取到的字节量

  • OutputStream是所有字节输出流的父类,其定义了基础的写出方法,常用的方法如下:
    — void wiret(int d)
    写一个字节,写出去的是给定的int的“低八位”
    — void write(byte[] d)
    将给定的字节数组中的所有字节全部写出

FileInputStream类

java.io.InputStream
|——java.io.FileInputStream

构造方法摘要

  • FileInputStream(File file/String fileName)
    通过打开一个到实际文件的连接来创建一个 FileInputStream

方法摘要

  • int read()
    从此输入流中读取一个数据字节。
  • int read(byte[] b)
    从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
  • int read(byte[] b, int off, int len)
    从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
  • long skip(long n)
    从输入流中跳过并丢弃 n 个字节的数据。
  • void close()
    关闭此文件输入流并释放与此流有关的所有系统资源。

字节流的输入流即是以字节为单位进行读取的,read()一次读取一个字节,read(byte[])即最多填满该数组,实际也是一次次一个个字节放入数组的,返回实际读入长度,read(byte[] b, int off, int len)则限定了读取的长度和存放的起始位置

BufferedInputStream类——带缓冲区升级版

  • BufferedInputStream(InputStream in)
    创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

方法摘要

  • int read()
    参见 InputStream 的 read 方法的常规协定。
  • int read(byte[] b, int off, int len)
    从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中。
  • long skip(long n)
    参见 InputStream 的 skip 方法的常规协定。

FileOutputStream类

java.io.OutputStream
|——java.io.FileOutputStream

构造方法摘要

  • FileOutputStream(File f / String name)
    创建一个向具有指定名称的文件中写入数据的输出文件流。
  • FileOutputStream(Filef / String name, boolean append)
    创建一个向具有指定 name 的文件中写入数据的输出文件流。并设置是否从末尾继续写

方法摘要

  • void write(byte[] b)
    将 b.length 个字节从指定 byte 数组写入此文件输出流中。
  • void write(byte[] b, int off, int len)
    将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
  • void write(int b)
    将指定字节写入此文件输出流。

BufferedOutputStream类——带缓冲区升级版
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

方法摘要

  • void flush()
    刷新此缓冲的输出流。
  • void write(byte[] b, int off, int len)
    将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。
  • void write(int b)
    将指定的字节写入此缓冲的输出流。

注意:使用带有缓冲区的输出流,数据是写入到缓冲区的,需要flush才能一次性将已经缓冲的内容写出到文件里面去

字符流

抽象超类:
Reader是字符输入流的父类;
Writer是字符输出流的父类。
字符流是以字符(char)为单位读写数据的。一次处理一个字符(Unicode)。字符流的底层仍然是基本的字节流。也就是说他们的创建也需要字节流来构建

Reader的常用方法:

  • int read()
    读取一个字符,返回的int值“低16”位有效
  • — int read(char[] chs)
    读取chs字符数组的length个字符并存入chs数组,返回值为实际读取到的字符量

Writer的常用方法:

  • void write(int c)
    写出一个字符,写出给定int值“低16位”表示的字符
  • void write(char[] chs)
    将给定chs数组中所有字符写出
  • void write(String str)
    将给定str字符串写出
  • void write(char[] chs, int offset, int len)
    将chs数组中从offset处开始连续的len个字符写出

InputStreamReader类——又称作转换流(桥梁)

字符输出流的创建不但需要字节流而且一定需要编码表。因为字节在不同的编码表中编码情况不同

  • InputStreamReader(InputStream in)
    创建一个使用默认字符集的 InputStreamReader。
  • InputStreamReader(InputStream in, Charset cs)
    创建使用给定字符集的 InputStreamReader。

方法摘要

  • int read()
    读取单个字符。
  • int read(char[] cbuf, int offset, int length)
    将字符读入数组中的某一部分。

它的方法可见都是以字符为单位进行操作的

他有个子类FileReader是可以直接通过文件构建,编码表直接默认(不灵活)!而FileReader的用法与之完全一致,纯继承而来!

BufferedReader类——字符流的缓冲升级版

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

他的方法唯一独特之处,也是最大亮点:能按行读取返回字符串

  • String readLine()
    读取一个文本行。实际就是读到/r/n位置为止

OutputStreamWriter类——字符输出流,也是一个转换流

同样的:只要是字符流,我们一定要给他一个编码表才能将字节转为字符单位输出

  • OutputStreamWriter(OutputStream out)
    创建使用默认字符编码的 OutputStreamWriter。
  • OutputStreamWriter(OutputStream out, Charset cs)
    创建使用给定字符集的 OutputStreamWriter。

方法摘要

  • void write(char[] cbuf, int off, int len)
    写入字符数组的某一部分。

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

  • void write(String str, int off, int len)
    写入字符串的某一部分。——只要是字符流,字符能写肯定能直接写字符串了

  • void close()
    关闭此流,先刷新它。

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

注意了:因为是字符输出流,它是要进行编码操作的,因此该类对象内部其实也有缓冲区为了查表的,所以他也是需要刷新/关闭流才能真正写入到文件中去的!

它的直接子类FileWriter也是类似FileReader,在用法上没有任何区别,而是它的初始化很简单,只需要通过文件即可构建FileWriter对象

BufferedWriter和PrintWriter类——字符输出流的缓冲升级版

BufferedWriter:
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入

构造器

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

方法:

  • void flush()
    刷新该流的缓冲。
  • void newLine()
    写入一个行分隔符。
  • void write(char[] cbuf, int off, int len)
    写入字符数组的某一部分。
  • void write(int c)
    写入单个字符。
  • void write(String s, int off, int len)
    写入字符串的某一部分。

PrintWriter
向文本输出流打印对象的格式化表示形式。

它的构造方法最多:

但其实归根结底就三类:用文件构建、用字节流构建、用字符流构建

  • PrintWriter(File file/String fileName)
    使用指定文件创建不具有自动行刷新的新 PrintWriter。
  • PrintWriter(File file/String fileName, String csn)
    创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
  • PrintWriter(OutputStream out)
    根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
  • PrintWriter(OutputStream out, boolean autoFlush)
    通过现有的 OutputStream 创建新的 PrintWriter。
  • PrintWriter(Writer out)
    创建不带自动行刷新的新 PrintWriter。
  • PrintWriter(Writer out, boolean autoFlush)
    创建新 PrintWriter。
public static void main(String[] args) throws Exception {
		/*
		 * 最复杂的、最灵活的,可以指定追加写(FileOutputStream)\指定编码表(字符流构造)\自动行刷新(PrintWriter构造)
		 */
		PrintWriter pw = new PrintWriter(new OutputStreamWriter
		(new FileOutputStream("filename",true),"gbk")
		,true);
		/*
		 * 直接通过字节流创建,无法指定编码表
		 */
		PrintWriter pw = new PrintWriter(new FileOutputStream("filename",true),true);
		
		/*
		 * 通过文件创建,都不能指定
		 */
		PrintWriter pw = new PrintWriter("filename");
	}

效率对比

读写方法比较
有数组辅助的必然更快
read(byte[]/char[]) / write(byte[]/char[]) > read(byte/char)/write(byte/char)

对象选取比较
有缓冲区的必然更快
Buffered > 无Buffered

@org.junit.Test
	public void test3() throws Exception {
		//非缓冲流进行文件复制
		InputStream is = new FileInputStream("Cisco Packet Tracer v7.2.0.0226 x64.rar");
		OutputStream os = new FileOutputStream("copy1.rar");
		byte[] buf = new byte[1024];
		int len = 0;
		long now = System.currentTimeMillis();
		while((len = is.read(buf))!= -1) {
			os.write(buf, 0, len);
		}
		is.close();
		os.close();
		System.out.println("耗时:"+(System.currentTimeMillis() - now)+"ms");
//		耗时:2250ms
	}
	@org.junit.Test
	public void test4() throws Exception {
		//缓冲流进行文件复制
		BufferedInputStream bis = new BufferedInputStream(
				new FileInputStream("Cisco Packet Tracer v7.2.0.0226 x64.rar"));
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream("copy2.rar"));
		byte[] buf = new byte[1024];
		int len = 0;
		long begin = System.currentTimeMillis();
		while((len = bis.read(buf))!= -1) {
			bos.write(buf, 0, len);
		}
		bis.close();
		bos.close();
		System.out.println("耗时:"+(System.currentTimeMillis() - begin)+"ms");
//		耗时:297ms
	}

缓冲原理

单字节一个个的复制文件
在这里插入图片描述
自建数组缓冲
在这里插入图片描述

带缓冲地复制文件
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值