文章目录

  • IO流
    • 概述
      • 简述
      • 分类
      • 步骤
    • 字节流
      • InputStream
        • FileInputStream
          • 概述
          • 构造方法
      • OutputStream
        • FileOutputStream
          • 构造方法
      • 字节流文件拷贝
        • 普通的
        • 高效缓冲字符流
    • 字符流
      • 概述
      • Reader
        • FileReader
      • Writer
        • FileWriter
          • 构造方法
      • 字符流文件拷贝
        • 普通的
        • 高效缓冲字符流
    • 选择字节流、字符流
    • 转换流
      • 编码表
      • 转换流
  • 练习
  • 疑惑

IO流

概述

简述

I\O:input、output。输入输出都是针对内存而言
input:输入,其他设备到内存
output:输出,内存到其他设备

什么是I\O流?

1)I\O就是设备之间进行数据交互的对象所属的类型
2)Java中操作设备之间数据传输的对象,都是IO流对象,这些对象所属的类型,都在io包中

分类

按照共能分为:

字节流:直接操作字节的流对象
字符流:直接操作字符的流对象

按照流向分为:

输入流:其他设备流到内存
输出流:内存流到其他设备

所以有四个顶层抽象类

字节流:字节输入流:InputStream字节输出流:OutputStream
字符流:字符输入流:Reader字符输出流:Writer

PS:根据不同的交互设备,有不同的具体子类,但是没必要那么详细,直接使用对应的顶层抽象类即可(向上转型)

步骤

1)导包导入io包
2)处理解决异常
3)关闭io流对象

字节流

计算机最小存储单位是字节,那么字节可以表示任意类型

字节流:
字节输入流:InputStream
字节输出流:OutputStream

InputStream

字节输入流的顶层抽象父类。因为其中的read()方法是抽象方法(不知道具体的交互设备),那么对应的类就是抽象类。

注意: InputStream是一个抽象类,那么创建对象时,使用用子类创建

方法

int read()从当前字节输入流中,读取并返回一个字节,未读到返回-1
注意既然是字节,为什么是int类型?因为字节不能表示负数,无法指名没有读到字节的情况,所以,将字节前面加24个0,变成intint read(byte[] arr)从当前字节输入流中,读取并存放在arr中,未读到返回-1。
注意连续使用时,会接着上次的内容继续读取并存放int available()剩余未读的字节个数
void close()4

FileInputStream

概述

InputStream具体的子类,最常用的,与磁盘交互

不仅一次可以读取一个字节,一次也可以读取很多字节
因为一切数据在计算机中都是以字节存储,所以FileInputStream可以读取任意文件,包括图片、视频、音频

构造方法

FileInputStream(File f)将file对象封装成字节输入流,将来可以读取文件的信息
FileInputStream(String path)将字符串(文件路径)封装成字节输入流,将来可以读取信息

注意:封装的文件对象都是针对文件本身而言,不是封装路径

 FileInputStream f = new FileInputStream("a.txt");byte[] arr = new byte[2];int length;while((length = f.read(arr)) != -1) {//第一次读取两个字节,并存放在arr中,arr{1,2}//第二次读取一个字节,并存放在arr中,arr{3,2},覆盖掉原本的0索引上的元素//第三次没有读取到字节,返回-1,并结束循环System.out.print(new String(arr,0,length) + "\t");System.out.println(f.available());}f.close();
 FileInputStream fis = new FileInputStream("D:\\www\\baidu\\test.txt");int a;while((a = fis.read()) != -1) {System.out.println(a);}

OutputStream

字节输出流的顶层抽象父类

注意: OutputStream是一个抽象类(不知道关联的具体的设备是什么),那么创建对象时,使用用子类创建

方法

void write(int b)
注意因为是字节流,而存储的又是int类型,所以存储时会将前三个字节(全是0)取消,只存后一个字节的内容
void write(byte[] arr)
void write(byte[] arr,int offest,int len)offest:索引开始的位置len:总共输出多少位
void close()

FileOutputStream

OutputStream具体的子类,最常用的,与磁盘交互

构造方法
FileOutputStream(String path)
FileOutputStream(File f)1)指定的路径不存在的,创建该文件2)指定的路径是存在的,清空该文件FileOutputStream(String path, boolean append)
FileOutputStream(File f, boolean append)1)指定的路径不存在,自动创建2)指定的路径存在,且append设置为true,则不会清空该文件,而是在后面追加
 FileOutputStream fos = new FileOutputStream("test.txt", true); //原内容为123byte[] arr = {65, 66, 67};fos.write(arr, 0, 2);//123ABfos.close();

字节流文件拷贝

普通的

一、低效率,使用内存少
一个字节一个字节的拷贝

FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("a_copy.txt");
int a = 0;//用于判断是否还有没读完的字节
while((a = fis.read()) != -1) {fos.write(a);
}fis.close();
fos.close();

二、高效率,连续占用的内存大,不贴近实际
使用一个数组一次拷贝

FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("a_copy_arr.txt");
byte[] arr = new byte[fis.available()];
fis.read(arr);
fos.write(arr);fis.close();
fos.close();

三、高效率,连续占用的内存较小,贴近实际
使用一个数组多次拷贝

FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("a_copy_arrs.txt");
byte[] arr = new byte[1024 * 8];
int len = 0;
while((len = fis.read(arr)) != -1) {fos.write(arr, 0, len);
}
fis.close();
fos.close();

高效缓冲字符流

加强普通的输入流、输出流,只是起一个加强作用,使用方式不变

构造方法
BufferedInputStream(字节输入流对象)
BufferedOutputStream(字节输出流对象)

FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("a_buffer.txt");BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int a =0;
while((a = bis.read()) != -1) {bos.write(a);
}bis.close();
bos.close();

高效原因?

BufferedInputStream 1)该类型底层准备了一个大小为8*1024大小的数组,调用者使用read()读取一个字节时,该对象一次读取8192个字节。2)将第一个字节返回给调用者,调用者第2次~第8192次再调用时,就不用去磁盘取数据了,直接从该数组取字节就好。3)当8192个字节读取完之后还需要取数据时,又在磁盘中挨着上次的8192个字节继续取数据即可BufferedOutputStream 1)当使用write()方法写出字节数据时,先将写出的数据存储在自己的数组中(8*1024个字节大小),当写出够8192字节数据时,一起刷新2)如果没写出够8192个字节时,关闭流之前刷新缓冲:底层有1204*8字节大小的数组,存储每次输入和输出的字节内容刷新:将缓冲区中的数据,写进磁盘中

特有方法

flush(),刷新(将缓冲区中的数据,写进磁盘中)bos.write(b);bos.flush();bos.close();

字符流

概述

字符类底层就是字节流。加强了字节流。因为每次读、写时,不知道到底需要读、写几个字节(因为可能存在汉字、英文等夹杂着的情况),所以加强字节流,变为字符流。

所以
如果要表示中就需要连续读取两个字节,表示英文又只需要读取一个字节。


由于关联的具体设备位置,所以定义的也是抽象类。

PS:GBK编码表中,如果读取的字节是正数,那么就是英文;如果读取的第一个字节是负数,那么就是中文(中文由两个字节表示)

Reader

字符输入流的顶层抽象类

注意: Reader是一个抽象类,那么创建对象时,使用用子类创建

方法

int read())从当前字节输入流中,读取并返回一个字节,未读到返回-1
注意既然是字符,为什么是int类型?因为字符不能表示负数,无法指名没有读到字节的情况,所以,将字符前面加16个0,变成int
int read(char[] arr)
void close()

FileReader

Reader的子类,最常用的,与磁盘交互

构造方法

FileReader(File f)
FileReader(String path)指定路径的文件,封装为字符输入流
FileReader r = new FileReader("b.txt");//因为要表示没读到字符的状态,而char不能表示负数,所以定义int(前两个字节用0填充),-1表示没读到int a = 0;while((a = r.read()) != -1) {//read返回的是int类型的,所以需要转型System.out.print((char)a + " ");}

Writer

字符输出流的顶层抽象类

方法

write(int c)
write(char[] chs)
write(char[] chs, int offset, int len)从offset索引开始,共len个字符写出到指定文件write(String str)将字符串编码形成字节数组之后,写出到目标文件去write(String str, int offset, int len)

FileWriter

Writer的子类,最常用的,与磁盘交互

构造方法
FileWriter(String path)
FileWrtier(File f)1)指定的路径不存在的,创建该文件2)指定的路径是存在的,清空该文件FileWriter(String path, boolean append)
FileWriter(File f, boolean append)1)指定的路径不存在,自动创建2)指定的路径存在,且append设置为true,则不会清空该文件,而是在后面追加
 FileWriter fw = new FileWriter("crush.txt");String str = "好久不见";fw.write(str, 0, 2);fw.close();

字符流文件拷贝


字符输入流
    字节——》GBK,GBK——》Unicode,Unicode——》int
字符输出流
    与字符输入流相反

普通的

 FileReader fr = new FileReader("c.txt");FileWriter fw = new FileWriter("c_copy.txt");int c;//每次读取到的字符while ((c = fr.read()) != -1) {fw.write(c);}fr.close();fw.close();

高效缓冲字符流

加强普通的输入流、输出流,只是起一个加强作用,使用方式不变

构造方法
BufferedReader(Reader r)
BufferedWriter(Writer w)

特有方法

1)BufferedReader
String readLine(),读取一整行,不包括换行符。返回null,表示没有可读的内容
注意:以换行符为每一次读取的结束符2)BufferedWriter
newLine(),可以提供一个跨平台的换行符windows中为\r\n;linux中为\n
public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new FileReader("demo.java"));BufferedWriter bw = new BufferedWriter(new FileWriter("demo_copy.java"));String a;while((a = br.readLine()) != null) {//读取一整行,没有下一行,返回null
//          System.out.println(a);bw.write(a);bw.newLine();//换行}br.close();bw.close();}

高效的原因同字节流一样

选择字节流、字符流

1)文件拷贝,最好使用高效缓冲字节流。因为字符类拷贝时,涉及很多操作,反而变慢了
2)关于字符的操作(除文件拷贝),使用字符流

转换流

编码表

字符集

含义:在字节和字符之间,相互转换时,查询的对应关系,就是编码表
常见编码表:GBK:定义了中文和英文的各种字符,一个英文使用一个字节表示,一个中文使用两个字节表示UTF-8:万国码提升形式,一个英文使用一个字节表示,一个中文使用三个字节表示
说明:一般在java的内存中,使用的编码都是Unicode编码,因为java中的字符都使用两个字节来表示在java的内存以外,会使用其他的编码形式,具体使用哪种,取决于文件的要求

转换流

就是将字节流包装成了字符流对象,可以直接操作字符

Reader                                   字符输入流的顶层抽象父类InputStreamReader               能自主确定解码形式的字符输入流构造方法InputStreamReader(InputStream is)将指定的字节流转成字符流,按照平台默认编码表解码InputStreamReader(InputStream is, String charSetName)当前转换流,按照指定的字符集来解码FileReader                  使用平台默认解码的操作文件的字符输入流Writer                               字符输出流的顶层抽象父类OutputStreamWriter              能自主确定编码形式的字符输出流构造方法OutputStreamWriter(OutputStream os)将指定的字节输出流转换成字符输出流,按照平台默认编码表编码OutputStreamWriter(OutputStream os, String charSetName)当前转换流,按照指定的字符集来编码FileWriter                     使用平台默认编码的操作文件的字符输出流

一、输入流关联键盘

 InputStream is = System.in;InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);System.out.println(br.readLine());

二、将一个uft8编码的文件内容,拷贝到一个gbk编码的文件中(eclipse中默认的编码表是Unicode,但是打开txt文本时,使用的编辑器默认是GBk解码的)

 private static void test_utf8_copy_gbk() throws  IOException {//      InputStream is = new FileInputStream("gbk_utf8.txt");
//      InputStreamReader fr = new InputStreamReader(is,"utf8");
//      OutputStream fw = new FileOutputStream("gbk_utf8_copy.txt");
//      OutputStreamWriter osw = new OutputStreamWriter(fw);InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_utf8.txt"),"utf8");FileWriter fw = new FileWriter("gbk_utf8_copy.txt");int a;while((a = isr.read()) != -1) {fw.write(a);}isr.close();fw.close();}

三、将一个gbk编码的文件的内容,拷贝到一个utf8编码的文件中(eclipse中默认的编码表是Unicode,但是打开txt文本时,使用的编辑器默认是GBk解码的)

public static void gbk_copy_utf8() throws IOException {//解码格式为GBK可以不写???FileReader fr = new FileReader("gbk_utf8_copy.txt");OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_utf8.txt"), "utf8");int a;while((a = fr.read()) != -1) {osw.write(a);}fr.close();osw.close();}

【注意】

一、读取、写出格式
读取时,解码格式必须和源文件的编码格式相同
写出时,编码格式必须和目标文件的编码格式相同

二、编码和解码
将字符转换为字节的方式称为编码(A——》65)
将字节转换为字符的方式称为解码(65——》A)


练习


疑惑

1、既然eclipse中文本默认是GBK编码,而java代码默认是Unicode编码,那么将GBK编码的文本拷贝到UTF8编码的文本时,读取中英文汉字混合的情况的时候为何没有乱码???

猜测

GBK——》Unicode
英文:1个字节——》2个字节,前面加8个0
汉字:2个字节——》2个字节
Unicode——》UTF8
英文:2个字节——》1个字节,去掉8个0
汉字:2个字节——》3个字节,前面加8个0

2、格式为GBK可以不写???
FileReader fr = new FileReader(“gbk_utf8_copy.txt”);
FileWriter fw = new FileWriter(“gbk_utf8_copy.txt”);

3、编码是字符变字节,为何读取时叫解码;写出时叫编码???

Java核心语法——IO流相关推荐

  1. JAVA核心知识点--IO流

    目录 一.JavaIO流的分类 输入流和输出流 字节流和字符流 节点流和处理流 二.InputStream,OutputStream,Reader和Writer 三.节点流 四.处理流 缓冲流 转换流 ...

  2. java中的IO流(超全)(超详解)结合实例轻松掌握

    java进阶之IO流 IO流的概念(大纲): 1.InputStream和OutputStream的继承关系图 2.Reader和Writer的继承关系图 3.文件专属流(加※为重点掌握) ※File ...

  3. java io流分为,Java中的IO流按照传输数据不同,可分为和

    Java中的IO流按照传输数据不同,可分为和 答:字节流 字符流 克里斯蒂安 · 麦茨指出:想象的能指就是电影的能指,作为象征的科学,在第三视野范围内的解读,它是( ) 答:建立在共同的永久的背景之中 ...

  4. 重新java系列之IO流

    重新java系列之IO流 内容介绍 学习目标 字符输入流 字符输入流[Reader] FileReader类 构造方法 读取字符数据 使用演示: 字符输出流 字符输出流[Writer] FileWri ...

  5. 猿创征文|Java中的IO流大家族 (两万字详解)

    目录 IO流 概述 分类 四大家族 需要掌握的16个流 文件专属 FileInputstream(读 字节) FileInputStream类的其他常用方法 FileOutputStream (写 字 ...

  6. 视频教程-极简Java五:IO流-Java

    极简Java五:IO流 华中科技大学毕业,十余年行业经验,曾带领团队完成CPN客户管理系统,并完成农业银行网站,乐途旅游网等网站的开发,在Java领域有深厚的积累,授课风格深入浅出,直指核心. 夏昊 ...

  7. 笔记整理2----Java语言基础(二)06 断点调试与数据加密+07 面向对象-类与对象+08 java常用API-基础+09 java集合+10 IO流-基础

    06 断点调试与数据加密+07 面向对象-类与对象+08 java常用API-基础+09 java集合+10 IO流-基础 第06天 java基础语法 今日内容介绍  Eclipse断点调试  基 ...

  8. java中io流实现哪个接口_第55节:Java当中的IO流-时间api(下)-上

    标题图 Java当中的IO流(下)-上日期和时间日期类:java.util.Date 系统时间:long time = System.currentTimeMillis();public class  ...

  9. Java中的IO流(六)

    上一篇<Java中的IO流(五)>把流中的打印流PrintStream,PrintWriter,序列流SequenceInputStream以及结合之前所记录的知识点完成了文件的切割与文件 ...

最新文章

  1. 《百面机器学习》---AI算法工程师求职必备“面经”
  2. Linux - 网络相关指令
  3. likelihood(似然) and likelihood function(似然函数)
  4. Python高级特性:切片
  5. python程序中断时,输出打印日志
  6. vc++ List Control控件获得所有选中行的序号
  7. Centos 7.3 搭建php7,mysql5.7,nginx1.10.1,redis
  8. vue router 懒加载实现
  9. Klevgrand DAW Cassette for Mac(磁带模拟效果器插件)
  10. 中债估值 收益率_收债
  11. ROS的激光雷达、 加速度计、 陀螺仪传感器
  12. 4.4.4系统不用ROOT激活xposed框架流程
  13. 台式计算机有线无线网卡设置,台式电脑怎么设置无线网络,详细教您台式电脑怎么设置无线网络...
  14. HTML+CSS+JS实现 ❤️3D立体魔方小游戏❤️
  15. 微信小程序加载图片报错
  16. 液滴模板水凝胶的温度控制形状变化(定制PNIPA/膨润土复合水凝胶/聚乙烯醇/魔芋胶复合凝胶/海藻酸钠(SA)/氧化石墨烯(GO)复合水凝胶/壳聚糖(CS)-g-PAM/氧化石墨烯(GO)复合水凝胶)
  17. stringstream切割字符串
  18. 单点遥信发送表里一般都有什么变量啊?
  19. 光源类型-CIE标准光源
  20. 好机会!IT工程师恭喜了!纳入工信部-工业互联网人才库!8月31日报名截止

热门文章

  1. STM32电路原理图
  2. nexus私服传项目-401 Unauthorized
  3. MySQL 备份 nb3 和 psc的区别
  4. Neo4j技能树学习之路
  5. 计算机课件文字,计算机应用基础_文字处理wordppt课件.ppt
  6. 工欲善其事必先利其器,利用搜狗输入法设置代码片段
  7. 使用DNS来屏蔽广告
  8. pygame小项目 ~ 3 :Python完成简易飞机大战
  9. 【VS2022引用其他项目的.cs文件】
  10. 影视广告之神器Cinema 4D