I/O流

整个大的分类,不二话,还是那四个,InputStream,OutputStream,Reader,Writer是所有流的基类(别抬杠,我知道RandomAccessFile除外)具体用到什么功能,就要去对InputSteam的方法进行重写,使用他们子类来完成。在这里我来整理一下提他们之间的关系和用法。

一、InputStream

BufferedInputStream字节缓冲输入流
InputStreamFileInputStream字节文件输入流
 ByteArrayInputStream字节数组输入流

 

其中BufferedInputStream应该是大家最经常用到的,为的是在使用InputStream时可以增加缓冲区,好处就是在于可以减少系统开支,增加效率,打个比喻,如果不用缓冲就像是一捧一捧的舀水,而用缓冲就像是一桶一桶的舀水,就可以减少两边来回跑的时间,也就是通过这样的方式来增加I/O效率。

      FileInputStram则是文件输入流了,在读入流文件的时候就需要他了(如影音,图片等文件),通常可以把他再套上BufferedInputStream使用。

BufferedInputStream bis = new BufferedInputStream(System.in);

因为BufferedInputStream 的默认缓冲区大小是8092KB也就是8M,所以在文件较小的时候(相较于8M)用过BufferedInputStream之后的I/O操作明显效率会比直接用FIleInputStream提高了很多,在等于8M或者大于8M的时候相差就不大了,但是整体来说还是推荐用BufferedInputStream的。

      BtyeArrayInputStream 这个起到字节与流之间的桥梁,可以将字节数组转换成流。

InputStream is = new ByteArrayInputStream(new byte[1024]);
new String(is.toString().getBytes(),"UTF-8");

二、OutputStream

 

BufferedOutputStream字节缓冲输出流FileOutputStream字节文件输出流ByteArrayOutputStream字节数组输出流

同样的,BufferedOutputStream是大家经常用到的,与BufferedInputStream同理,增加缓冲区,减少系统开支,增加I/O效率。

      FileOutputStream则是文件输出流,在写出文件的用的就是他,也是通常可以把他套上BufferedOutputStream使用。

BufferedOutputStream bis = new BufferedOutputStream(new FileOutputStream(""));

ByteArrayOutputStream 你可以将要输出的字节数组读到内存缓冲区,然后要进行你所需要的操作。

ByteArrayOutputStream bos = new ByteArrayOutputStream();

 bos.write(new byte[1024]);

三、Reader

BufferedReader字符缓冲流
ReaderInputStreamReader字节->字符输入流
 FileReader字符文件输入流

 

Reader也同样提供了对应的字符缓冲流来提高效率。

      InputStreamReader则是搭起了字节流与字符流的桥梁。

Reader reader = new InputStreamReader(System.in);​

FileReader是当读取文件为​文本文件时(如TXT文件),可以直接用FIleReader进行操作,同样的在外面可以套上BufferedReader进行使用。

BufferedReader br= new BufferedReader(new FileReader(""));
  BufferedWriter字符输出流
WriterOutputStreamWriter字节->字符输出流
 FileWriter字符文件输出流
 PrintWriter打印流

 

Writer有他对应的BufferedWriter来增加I/O效率。

      OutputStreamWriter也是搭起了字符流与字节流的桥梁。

Writer writer = new OutputStreamWriter(System.err);

FileWriter是需要将字符写入文件时,可以直接用FIleWriter进行操作,同样的在外面可以套上BufferedWriter进行使用。

BufferedWriter writer = new BufferedWriter(new FileWriter(""));

但是Writer有一个BufferedWriter的加强类(可以这么理解)-PrintWriter,一般情况下推荐使用PrintWriter对外进行输出,他和BufferedWriter相比较来说,具有几个优点。

  1. PrintWriter的print、println方法可以接受任意类型的参数,而BufferedWriter的write方法只能接受字符、字符数组和字符串。

  2. PrintWriter的println方法自动添加换行,BufferedWriter需要显示调用newLine方法。

  3. PrintWriter的构造方法更广,可通过指定参数,实现自动刷新缓存(autoflush),而BufferedWriter需要通过flush方法来进行刷新。

  4. 同时PrintWriter在过程中不会抛出异常,如果关心异常,则要用checkError()来进行查看


五、总结

上面就是常见流的四大基类以及各自的子类,下面写几个对于流的一些日常使用例子。

      案例1:通过oss的sdk拿到byte字节流之后,要在页面上进行内容的加载(txt为文档)。

StringBulider sb = new StringBuilder();  //  声明好最后返回的字符串,先用StringBuilder类型

byte[] bytes = new byte[8096];  //这里new一个字节数组模拟从oss上拿到数组

InputStream input = new ByteArrayInputeStream(bytes);  //将字节数字转成字节输入流。

Reader reader = new InputStreadmReader(input,"UTF-8"); //将字节输入流转成字符输入流,字符格式使用utf-8

BufferedReader br = new BufferReader(reader);   //套上缓冲流

String line = "";  //每次读到的字符

whiel((line = reader.readLine()) != null) {  //每次去读文件的一行

sb.append(line).append("\n"); //将读到的一行内容给sb加上去,并且加换行符。
}
复制代码

      最后将sb.toString进行返回就可以了,前端可以用pre标签直接接收以保持在后端已经设定好的格式内容。

      案例2:写的一个将流进行字符转换的工具类。一开始代码是这样写的。

 InputeStream in = System.in;

 StringBulid sb = new StringBuild;

 byte[] bytes = new byte[256];

 int len  = 0;

 while((len = in.read(bytes)) != -1) {

 sb.append(new String(bytes, 0, len));

 }
复制代码

      最后把sb.toString进行return就结束,小伙伴们看着有啥问题没?其实逻辑没错啊,这样写也没错啊,但是!!!但是日常使用中偶尔会有几个乱码出现,我就没想明白啊,字符集的问题吧,系统默认字符集给的是utf-8啊,不应该有乱码啊,而且偶尔蹦出来几个字是乱码,这是什么鬼,后来还是被被人一语道破,卧槽,Java中的字符集为utf-8的汉字是占3个字节,如果字数比较多的话,每次到最后取的字节就取不完整,就可能造成乱码问题,经过修复后代码如下。

InputeStream in = System.in;

ByteArrayOutputstream bos= new ByteArratOutputStream();

byte[] bytes = new byte[256];

int len  = 0;

while((len = in.read(bytes)) != -1) {

bos.write(bytes, 0, len);

}
复制代码

      因为每次都是将取出来的字节都存放到字节数组里,所以即使这一次取的将一个完整的汉字的3个字节打乱,也没有关系,会在下一次取数的时候给拼过来,只是将完整的字节输入流转换成了字节数组输出流,最后将new String(bos.toByteArray(),"UTF-8")进行返回就可以了。


作者:小年年
链接:https://juejin.im/post/5b58a5886fb9a04fb136eb44
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值