热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

IO流基本知识总结【字节输入输出流、字符输入输出流、转换流、对象流】

1.概述:流是可以承载东西的数据流;java中io流也是用来承载运输数据的。2.分类:1.按流向分:【参考内存࿱

1.概述:
流是可以承载东西的数据流;java中io流也是用来承载运输数据的。

2.分类:
1.按流向分:【参考内存:进入内存叫做输入,出内存叫做输出】
1.输入流:承载数据进入内存的流叫做输入流
2.输出流:承载数据从内存中出来到磁盘中的流叫做输出流
2.按功能分:【操作的数据的组成类型】
1.字节流:流承载的数据是字节数据类型【操作的数据是字节】
2.字符流:流承载的数据是字符数据类型【操作的数据是字符】
3.字节分为:
字节输入流【InputStream】
字节输出流【OutputStream】
4.按字符分为:
字符输入流:【Reader】
字符输出流:【Wirter】

3.字节流
**概述:**每次传输的数据是以字节为单位进行传输的流,叫做字节流
一切皆为字节:
计算机可以存储各种各样的资源,其本质是使用数字【二进制】,所有的资源对应的都有一个数字在计算机中,这数字就理解为字节
字节输入流【InputStream】
概述:以字节为单位把数据放到内存中的流
常用方法:
read():一次读一个字节的数据到内存中
read(byte[] bytes):一次使用bytes去读取多个字节数据到内存中
inputStream是一个字节输入流的顶层抽象类,不能创建对象,只能去使用它的子类对象来使用这些行为
FileInputStream
概述:它是字节输入流用于内存和磁盘文件之间交互数据的一个字节输入流
构造方法:
FileInputStream(String path):创建一个以path地址为目标的文本输入流
FIleInputStream(File file):创建一个以file对象为目标的文本字节输入流
常用方法:
read():每次读取一个字节到内存中
注意事项:同一个字节输入流对象每次读完字节,光标【指针】向下个位置移动。
read(byte【】 bytes):每次读取多个字节到数组,再把数组中的字节数一次性读取到内存中
注意事项:
1.使用字节数组读取内容,不能保证每次都能把数组读满,取读到的数据的时候只读取每次读到的有效数据个数
2.当读数据读到末尾时,再去读取数据由于已经没有数据可以读取了,直接返回-1.【读取数据读到是-1意味着读完了】
返回值对比:
1.使用数组读取内容的返回值是int数字,代表的是每次读取到的有效字节个数。
2.一次只读取一个字节的时候返回值是int数字,代表的是读到的字节数据本身。
字节输出流【OutputStream】
概述:它是字节输出流的顶层抽象类,它是内存和外界文件进行数据交互的输出流。以字节为操作单位的
常用方法:
write(int bytes):一次只写出一个字节的数据到磁盘文件【目标文件】中
write[byte[] bytes]:一次写出数组中全部的字节的数据到磁盘文件中【借助于字节数组】
write(byte[] bytes,int starIndex,int len):一次性的写出字节数组中指定的多个字节数据到磁盘文件中。
starIndex:从数组的那个索引开始【开始的索引】
len:写多少个字节出去【字节的个数】
OutputStream是一个抽象类,不能创建对象,不能直接使用这些行为,只能找他的子类。根据设备的不同会有不同的子类,学习其中的一个FileOutputStream
FIleOutputStream
**概述:**是一个OutputStream的子类,用于内存和磁盘设备之间进行数据交互的输出流
构造方法:
FileOutputStream(String path):创建以path地址为目标文件的输出流对象
FileOutputStream(File file):创建以file对象为目标文件的输出流对象
基本功能:
write(int bytes):一次只写出一个字节的数据到磁盘文件【目标文件】中
write(byte[] bytes):一次写出数组中全部的字节的数组到磁盘文件中【借助于字节数组】
write(byte[] bytes,int starIndes,int len):一次性的写出字节数组中指定的多个字节数据到磁盘文件中 starIndex:从数组的那个索引开始【开始的索引】、len:写多少个字节出去【字节的个数】
注意事项:
使用输出流的时候,创建流对象会去判断指定的目标文件是否存在,存在直接格式化目标文件,不存在,自动的给我们创建一个目标文件。
文件续写:
构造方法:
FileOutputStream(String path,true):续写构造
FIleOutputStream(File file,true):续写构造
构造方法的参数加了true,创建输出对象的时候就不会格式化已经存在的目标文件

4.字节高效缓冲流
概述:用来给基本流进行提速的
答疑:
高效流具有操作文件数据的功能吗? 没有,但是可以对数据进行读写【可以调用基本流的功能】,因为内部的流对象是基本流对象。真正做事的还是基本流
字节输入缓冲流【BufferedInputStream】
字节输入缓冲流:BufferedInputStream
概述:经过缓冲提速的使用字节输入流进行读的IO流
构造方法:
BufferedInputStream(InputStream in):创建一个参数in字节输入流对象的缓冲流对象
常用方法:
read():一个一个字节的读取
read(byte[] bytes):多个字节的读取
工作原理:【面试题】
第一次文件中读取的时候,缓冲流对象使用了一个长度为8192的字节数组先一次性的读满该数组到内存的缓冲区中,基本io对象再读取的时候每次读取到的内容先到这个缓冲区中来拿,一直到数组内容不够了,缓冲流对象再到文件中读取8192个字节继续给io读取。这样减少了文件和内存的交流次数提升了效率
字节输出缓冲流:【BufferedOutputStream】
概述:就是给字节输出流提速的io流
工作原理:【面试题】
输出之前,缓冲流对象先在内存中搞了长度为8192的字节数组的缓冲区,优先把写出去的内容写到这个数组中,一直到数组写满了,自动的调用flush方法刷新缓冲区,把里面的所有内容写到目标文件中,如果没有写满可以手动调用flush方法刷新缓冲区,内容就会写到目标文件中
缓冲区什么时候将内容写入到文件中?
1.缓冲区满了,缓冲流对象自动调用fulsh方法
2.手动调用flush方法
3.关闭缓冲输出流对象【调用close方法】,先调用flush方法刷新缓冲区
构造方法:
BufferedOutputStream(OutputStream out):创建一个可以给out输出流加速的缓冲流对象
常用方法:
close():关闭流资源
flush():刷新输出流并强制写出所有缓冲的输出字节【清空缓冲区内容到目标文件中】
write(int a):单个字节的写入
write(byte[] bytes):多个字节的写入
write(byte[] bytes,int index,int length):数组中部分字节的写入
close()和flush()对比【笔试题】
相同点:
都可以刷新缓冲区,将内容书写到目标文件中
不同点:
flush():
1.刷新缓冲区,调用者是输出缓冲流对象属于输出缓冲流
2.flush方法调用后io流对象继续存在,并能够继续使用
close():
1.关闭流对象的,调用者可以是所有流对象,属于所有io流
2.close方法调用后io流对象就消失了,不能使用,再使用会Stream closed异常
注意事项:
flush方法虽然有刷新缓冲区的作用,但是不建议频繁使用。频繁的使用消除了缓冲区的作用。

5.字符流
1.编码:
把字符按照一定的方式转换为对应的数字,【就是把内存中的资源存放到磁盘文件的过程;磁盘文件中存放的都是数字】【以字节的方式存储的】
2.解码
把文件中的存储的数字按照一定的方式转换为对应的字符。
3.乱码的原因:
编码使用的转换方式和解码使用的转换方式如果一致的看到的就是正常的内容。
编码使用的转换方式如果不一致看到的就是乱码
读取或者写入使用的字符集和目标文件的字符集不一致导致乱码
4.使用字节流处理字符的问题:
1.使用字节流写字符【字符串】
可以使用,但是需要先把字符串【字符】转成字节数组,再存储到文件中,比较麻烦
字符->字节数->进行写出【写到文件中】
2.使用字节流读取字符
如果是纯英文,可以一次读取一个字节或者读多个没有影响
如果是纯中文,可以一次读取两个字节【GBK】那就可以,到那时读取三个自己就会乱码。
如果是中英文混杂,每次不知道读取多少个字节,因此无论字节数组准备多大,都有可能出现乱码导致字节流操作纯文本文件的时候会出现乱码的现象。
5.字符流的概述:
以字符单位进行读写数据的io流。只能操作纯文本文件,比如:图片也是字节组成的,但是它的字节再任何的字符集中是没有对应的字符的,字符流操作不了非纯文本文件的。
分类:
字符输入流:Reader【抽象类】
字符输出流:Writer[抽象类]
作用:传输字符型数据
6.字符输入流【Reader】
概述:以字符为单位进行输入内存数据的io流,是一个抽象类【字符输入顶层类】
常用功能:
read():每次读一个字符
read(char[] ch):每次的读取一个字符数组的内容
7.FIleReader【文本字符输入流】
概述:是字符输入流的子类,主要用来实现父类的功能;用于内存和磁盘之间的数据交互
构造方法:
FileReader(File file):创建以file为读取目标的字符流对象
FIleReader(String path):创建以地址path为读取目标的字符流对象
常用方法
read():每次读一个字符
read(char[] ch):每次的读取一个字符数组的内容
7.字符输出流:【Writer】
**概述:**以字符为单位进行输出数据的io流,是字符输出流的顶层抽象类
**特点:**自带缓冲区【写出去优先写到缓冲区,要想写出的东西到目标文件中就需要刷新缓冲区】
常用功能:
write(int b):一次写出一个 字符
write(char[] ch ):一次写出一个字符数组的内容
write(char【】 ch,int index,int len):一次写出一个字符数组中指定的内容
write(String s):一次性写出一段话
flush():刷新缓冲区
FileWriter:【字符输出流的子类】
**概述:**是writer的子类,是用来实现Writer的子类,是用来实现Writer的基本功能的,目的是完成内存和磁盘文件之间的数据交互
构造方法:
FIleWriter(File file):创建以file为输出目标的字符输出流对象
FileWriter(String path):创建path地址为输出目标的字符输出流对象
常用方法:
write(int b):一次写出一个字符
write(char[] ch ):一次写出一个字符数组的内容
write(char【】 ch,int index,int len):一次写出一个字符数组中指定的内容
write(String s):一次性写出一段话
flush():刷新缓冲区
问题::字符流是否可以操作非纯文本文件?
结论:可以操作,但是不会出现正确的结果【即不可以】
原因:字符流操作数据的时候,先把数据变成字节,再把字节按照规定的字符集转换成字节对应的字符,进行操作。非纯文本文件转换为字节后,这些字节再字符集没有对应的字符,转不成字符,字符流没法正确的操作数据。
注意事项:使用io流进行复制的时候,源文件和目标文件是同一个文件,会发生内容消失。
文件续写:
使用构造方法可以完成续写的功能
构造方法:【续写构造】
FIleWriter(String path,true)
FileWriter(File file ,true)
这样的构造方法,创建对象的时候,就不会对已经存在的文件进行格式化了,保留源文件的内容,再写的时候再已有内容的尾部进行追加续写

6.字符高效缓冲流:
概述:
就是一个可以使字符流的工作效率提升的一个工具流
分类:
BufferedReader:字符输入缓冲流
BufferedWriter:字符输出缓冲流
BufferedReader【字符输入缓冲流】的使用:
构造方法:
BufferedReader(Reader r):创建一个可以给r流对象提效的对象
常用方法:
read():每次读一个字符
read(char【】 ch):每次的读取一个字符数组的内容
特有方法:
readline():每次读一行
BufferedWriter【字符输出高效流也就缓冲流】的使用
概述:就是一个可以使字符输出流的工作效率提升的一个工具流
构造方法:
BufferedWriter(Writer w):创建一个给w字符输出流提效的缓冲流对象
常用方法:
write(int b):一次写出一个字符
write (char【】 ch):一次写出一个字符数组的内容
write(char【】 ch,int index,int len):一次写出一个字符数组中指定的内容
write(String s):一次性写出一段话
flush():刷新缓冲区
newLine():换行【和“\r\n”、“\r”、"\n"的效果一样】

7.高效的原因:【缓冲区原理】
高效输入缓冲流:
每次缓冲流对象读取的时候,一次性的读了8192个内容放到一个数组中,将该数组暂时存放到内存中【缓冲区】提供给修饰的基本流对象进行每次的读取,从而达到了提效的效果
高效输出缓冲流:
第一次输出的时候先创建一个大小为8192的数组暂时存放再内存中【缓冲区】,基本流每次写内容先到缓冲区,满了自动的一次性的写到文件中,从而达到了提效。

8.转换流【工具流】
**概述:**是一个能够在字节流和字符流之间相互转换的io流【工具流】
**本质:**是字符流的子类但是本质上是一个字符流,他拥有字符流所有的功能,也可以被字符缓冲流加强【可以把字节流变成字符流】
OutputStreamWriter:字符流到字节流的桥梁;即【以字符的形式写出去,文件接受到的是字节形式】
构造方法:
OutputStreamWriter(OutputStream os,String charSetName)
解释:【String charSetName参数可给可不给:给就按给定的字符集创建对象;不给;就按照默认的字符集创建对象】
InputStreamReader:字节流到字符流的桥梁,可以指定编码形式【按照指定的编码集的字节格式去读取内容到内存中的一个位置,然后 再把这些读到的字节按照编码集转换成对应的字符,使用字符流读取到目标内存中】
构造方法:
InputStreamReader(InputStream is,String charsetName) 【String charSetName参数可给可不给;给就按给定的字符集创建对象;不给;就按照默认的字符集创建对象/】
使用:直接使用Reader类中的方法即可(该类是Reader的子类)常用方法就是字符输入流的常用方法。
注意事项:
1.无论是读取还是写出的时候,都需要参考读取文件和目标文件的编码形式【不一致会发生乱码现象优先选择转换流。】
2.读取源文件时,解码的形式【流的编码集】必须和源文件的编码形式一致【避免乱码】
3.写出目标文件时,编码形式必须和目标文件的编码形式一致【这样可以避免乱码】

9.对象流
**概述:**操作java对象资源数据的流;概述:用于将内存中的对象内容数据写出到磁盘文件中保存
对象输出流【对象序列化流】
**序列化:**就是把内存中的数据写出到磁盘文件中的行为叫做序列化【数据的瞬时态转变为持久态】
作用:
就是把对象型数据写入到磁盘文件中【数据的持久化;瞬时态到持久态。】
构造方法:
ObjectOutputStream(OutputStream os):创建一个序列化流对象【使os字节输出流拥有序列化的功能】
说明:序列化流是一个字节流,拥有字节流的所有共性行为,但是一般不用
特色成员方法:
writeObject(Object o):将对象o中的数内容写到指定磁盘文件
注意事项:
1.对象序列化流使用前提:
写出的对象的类型必须实现Serializable接口
面试题: 序列化数据,必须要实现Seriablizable接口?
不一定,序列化数据有很多种方式,不一定实现接口。序列化对象型数据时常用序列化流,要求对象类型类必须实现Serializable接口2.序列化之后的磁盘文件内容看不懂,计算机可以看懂的东西。
对象输入流【反序列化流】:【ObjectInputStream】
**1.概述:**是将磁盘文件中的对象数据【序列化过来】读到内存中的io流
**2.前提:**操作的文件内容一定是序列化数据
**3.作用:**把磁盘文件中的对象数据读到内存中【数据持久态到瞬时态】
4.构造方法:
ObjectInputStream(InputStream in):创建一个反序列化流对象【让字节输入流in拥有反序列化功能。】
5.特有方法:
readObject():读取文件中的任意类型对象数据。
序列化或反序列化的注意事项:
1.序列化的时候一个文件可以序列化多种数据类型的对象
2.无论是序列化还是反序列化特有方法调用一次只能操作一个对象 【如何操作多个对象,把多个对象放到一个集合对象中,序列化集合,反序列化回来也是一个集合】
3.操作的文件内容一般是序列化过来的内容
4.序列化的文件不能人为的修改
5.序列化之后如果对象类型发生改变:属性发生改变,会影响反序列化操作


推荐阅读
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
author-avatar
coffee_陈--嘉辉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有