JAVA基础-IO流复习笔记

JAVA基础-IO流复习笔记

一、什么是io流

  • "i"指的是input;"o"指的是output;
  • “流”是一种抽象概念,就像一个数据通道。
  • io流就是数据输入输出的通道。
  • 输入输出是相对于计算机内存而言的。数据从内存到外部设备是输出,反之是输入。
  • java提供了一系列的API来实现“流”。

二、流的分类

1,按数据流向分类:

  • 输入流
  • 输出流

2,按一次文件交互操作的数据单位分类:

  • 字节流

  • 字符流

    ​ ???再确认一下

    • 字符输入流会首先创建默认的缓冲区,长度为8192的字节数组,程序每次(一次读取的单位是一个字符)读取数据时先在缓冲区查看有无数据,有就读缓冲区,没有就会读文件,使数据尽量装满缓冲区以后,再读缓冲区。

    • 字符输出流同样有缓冲区,以下情况会将数据正式写到外部文件中:

      • 缓冲区装满了。
      • 调用flush()方法,手动刷新数据到文件。
      • 释放资源,close()。不过流一旦关闭,就不能再继续写数据了

3,按功能分类:

  • 节点流:直接操作数据读写的(java中的类)。
  • 处理流(或者叫过滤流):处理流相当于修饰节点流的类,它的参数就是节点流。处理流最终还是使用的节点流的功能。底层使用修饰器模式实现。常用处理流:缓冲流。

三、相关的API

1、四个抽象类基类

image-20230108223657868

2,字节输入流(常用)

InputStream

3、字节输出流(常用)

OutputStreaM

4,字符输入流(常用)

Reader

5,字符输出流(常用)

Writer

6,File 文件对象

文件对象,表示一个抽象的文件,可能实际存在,也可不存在;可以是文件,也可以是文件夹。

常用方法

  • 构造方法
new File(String path);	//1
new File(String parent,String child);	//2
new File(File parent,String child);	//3
new File(URI uri); //4
  • 其他方法

    • 获取文件名、各种路径、文件长度(单位:字节)、修改时间(lastModified);
    • 获取获取所有的根目录文件对象列表(静态方法);
    • 获取目录下的所有文件名或文件对象列表;
    方法说明
    String[] list(FileNameFilter filter)这个方法可以传入一个过滤器对象,添加一些过滤条件。
    String[] listFiles(FileNameFilter filter)这个方法可以传入一个过滤器对象,添加一些过滤条件。
    • 判断文件或文件夹是否存在;
    • 判断是否为文件、是否为文件夹;
    • 判断是否是隐藏的文件或目录;
    • 判断该抽象路径是否是绝对路径;
    • 判断是否可读、是否可写;
    • 创建文件、文件夹、多级文件夹;
    • 重命名和剪切文件;
    方法说明
    boolean renameTo(File file);将file1对应的文件截切到file2文件位置,并且名字改为file2的。file2对应的文件必须是不存在的。文件夹同理。
    • 删除文件或文件夹;
    方法说明
    boolean delete()删除文件或空文件夹。不能删除非空文件夹。
    void deleteOnExit()jvm退出的时候删除文件或文件夹。常用于删除临时文件,无返回值;

四、FileInputStream和FileOutputStream

1、FileInputStream

万能的文件字节输入流。节点流。任何文件都可以用这个流读取。

  • 构造方法
方法说明
FileInputStream(String name)
FileInputStream(File file)
  • 其他方法
方法说明
int read();读一个字节,然后指针后移。返回值为该字节ASCII码。
int read(byte[] buffer);读一个字节数组的数据。返回值为读到的字节个数。
int read(byte[] buffer,int off,int len);读len个字节的数据,从buffer数组下标为off的位置存入数据。
int available();返回文件的有效字节数。
long skip(long n);跳过n个字节;

2、FileOutputStream

文件字节输出流。节点流。

  • 构造方法
方法说明
FileOutputStream(String name)
FileOutputStream(File file)
  • 其他方法
方法说明
void write(int b);将一个字节的数据写到文件中;
void write(byte[] buffer);将一个字节数组的数据写到文件中;
void write(byte[] buffer,int off,int len);将字节数组从off位置,长度为len的数据写到文件中;
void fiush();刷新。

五、FileReader和FileWriter

1、FileReader

字符输入流。节点流。用于读取普通文本。

  • 构造方法

和字节流的构造类似。

  • 其他方法(略)

写数据的方法,和字节流类似。不同点在于,操作数据的单位是字符。

2、FileWritert

字符输出流。节点流。

  • 构造方法

和字节流的构造类似。注意第二个boolean类型的参数表示是否是在文件末尾追加数据。默认值是false,表示清空重写。

  • 其他方法(略)

写数据的方法,可以使用int(写入对应的ASCll码的数据)、char[]、String类型的数据写入文件。

六、缓冲区

1,缓冲区是什么?

缓冲区 (buffer)就是内存中预留的一段内存空间。

2,缓冲区的作用:

  • 防止低速设备限制高速设备。数据直接送往缓冲区,高速设备不用再等待低速设备。 例如:使用打印机打印文档,由于打印机的打印速度相对较慢,可以先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时CPU可以处理别的事情。
  • 提高单次数据读写的数据量,减少数据的读写次数。将数据送往缓冲区,待缓冲区满后再进行传输,这样可以节省很多时间。例如:我们想将数据写入到磁盘中,不是立马将数据写到磁盘中,而是先输入缓冲区中,当缓冲区满了以后,再将数据写入到磁盘中,这样就可以减少磁盘的读写次数。

3,注意

字符流自带缓冲区,所以字符流缓冲流效率的提升没有字节缓冲流明显。

七、BufferedInputStream

字节输入缓冲流。处理流。

  • 构造方法
方法说明
BufferedInputStream(OutputStream out);
BufferedInputStream(OutputStream out,int size);size可以指定缓冲区大小
  • 其他方法(略)

主要有读数据、刷新流、关闭流的方法。

八、BufferedOutputStream

字节输出缓冲流。处理流。

  • 构造方法(略)
  • 其他方法(略)

九、缓冲流读写数据实践

  • 源文件:“C:\Users\86152\Desktop\src.txt”, 大小:40kb

1、字节输入流 + 字节输出流

    private void NoBuffer() throws IOException {

        //字节输出流
        FileOutputStream os = new FileOutputStream("C:\\Users\\86152\\Desktop\\NoBuffer.txt");
        //字节输入流
        FileInputStream is = new FileInputStream("C:\\Users\\86152\\Desktop\\src.txt");

        int i = -2;
        while ((i=is.read())!=-1){
            os.write(i);
        }

        is.close();
        os.close();

    }

    @Test
    public void t1() throws Exception {

        long startTime1 = System.currentTimeMillis();
        NoBuffer();
        long endTime1 = System.currentTimeMillis();
        long time = endTime1-startTime1;

        System.out.println("Time:" + time);

    }

大约耗时:560

2、字节缓冲输入流 + 字节输出流

    private void Buffer() throws IOException {

        //字节输入
        FileInputStream is = new FileInputStream("C:\\Users\\86152\\Desktop\\src.txt");
        //字节输出
        FileOutputStream os = new FileOutputStream("C:\\Users\\86152\\Desktop\\Buffer.txt");

        //缓冲输入
        BufferedInputStream bis = new BufferedInputStream(is);

        int i = -2;
        while ((i=bis.read())!=-1){
            os.write(i);
        }

        bis.close();
        os.close();

    }

    @Test
    public void t1() throws Exception {

        long startTime1 = System.currentTimeMillis();
        Buffer();
        long endTime1 = System.currentTimeMillis();
        long time = endTime1-startTime1;

        System.out.println("Time:" + time);

    }

大约耗时:490

3、字节输入流 + 字节缓冲输出流

private void Buffer() throws IOException {

        //字节输入
        FileInputStream is = new FileInputStream("C:\\Users\\86152\\Desktop\\src.txt");
        //字节输出
        FileOutputStream os = new FileOutputStream("C:\\Users\\86152\\Desktop\\Buffer.txt");

        //缓冲输出
        BufferedOutputStream bos = new BufferedOutputStream(os);

        int i = -2;
        while ((i=is.read())!=-1){
            bos.write(i);
        }

        is.close();
        bos.close();

    }

    @Test
    public void t1() throws Exception {

        long startTime1 = System.currentTimeMillis();
        Buffer();
        long endTime1 = System.currentTimeMillis();
        long time = endTime1-startTime1;

        System.out.println("Time:" + time);

    }

大约耗时:70

4、字节缓冲输入流 + 字节缓冲输出流

private void Buffer() throws IOException {

        //字节输入
        FileInputStream is = new FileInputStream("C:\\Users\\86152\\Desktop\\src.txt");
        //字节输出
        FileOutputStream os = new FileOutputStream("C:\\Users\\86152\\Desktop\\Buffer.txt");

        //缓冲输入
        BufferedInputStream bis = new BufferedInputStream(is);
        //缓冲输出
        BufferedOutputStream bos = new BufferedOutputStream(os);

        int i = -2;
        while ((i=bis.read())!=-1){
            bos.write(i);
        }

        bis.close();
        bos.close();

    }

大约耗时:3

5、其他

以前一直有个问题:为什么使用缓冲流的时候,同样是在循环中一次读一个字节、写一个字节,相比于不用缓冲流时,效率高很多?

以下做了一个小实验,已知缓冲流在底层默认创建了一个长度为8192的字节数组作为缓冲区,循环读写一个缓冲区大小的数据前后,打开文件看看其中是否有内容。

1、首先不使用缓冲流,读写过程中打开文件查看是否有内容
private void NoBuffer() throws IOException {

        //字节输入
        FileInputStream is = new FileInputStream("C:\\Users\\86152\\Desktop\\src.txt");
        //字节输出
        FileOutputStream os = new FileOutputStream("C:\\Users\\86152\\Desktop\\Buffer.txt");

        int i = -2;
        int count = 0;	//计数,表示写到第几个字节了。
        while ((i=is.read())!=-1){
            os.write(i);	//这里设置断点
            count++;
        }

        is.close();
        os.close();

    }

    @Test
    public void test() throws Exception {

        NoBuffer();

    }
  • debug运行test(),分别在读取1、2、3个字节时打开文件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S8dw39iw-1673330982822)(https://gitee.com/lu-yunji/image/raw/master/image-20230109234953188.png)]

image-20230109235256982

image-20230109235343526

  • 如上所示:读一个写一个,效率不高。
2、使用缓冲区
private void Buffer() throws IOException {

        //字节输入
        FileInputStream is = new FileInputStream("C:\\Users\\86152\\Desktop\\src.txt");
        //字节输出
        FileOutputStream os = new FileOutputStream("C:\\Users\\86152\\Desktop\\Buffer.txt");

        //缓冲输出
        BufferedOutputStream bos = new BufferedOutputStream(os);

        int i = -2;
        int count = 0;	//计数,用于表示读到第几个字节了。
        while ((i=is.read())!=-1){

            count++;
            bos.write(i);

            if (count==8192){
                System.out.println("读取的数据未满一个缓冲区");	//这里设置断点1
            }
            if (count==8193){
                System.out.println("读取的数据刚好一个缓冲区");	//这里设置断点2
            }

        }

        is.close();
        bos.close();

    }

    @Test
    public void test() throws Exception {

        Buffer();

    }
  • debug运行test(),断点1(未满一个缓冲区时)的时候打开文件Buffer.txt,如下所示,没有内容:

image-20230109233448862

  • 继续运行,断点2(读满一个缓冲区时)的时候打开文件Buffer.txt,如下所示,一次直接写入了一个缓冲区大小的数据

image-20230109233729333

  • 结论:以上实验说明,虽然在代码的循环中,看似是读一个字节(调用read方法)即写一个字节(调用write方法),但是读到的数据并未在输出流调用write方法时立即写到文件上,而是暂存在了内存中的缓冲区里,等到缓冲区满时才真正写到文件上。

九、BufferedReader

字符输入缓冲流。处理流。

  • 构造方法(略)
  • 其他方法(略)
  • 特有成员方法
方法说明
void readline()读一个文本行

十、BufferedWriter

字符输出缓冲流。处理流。

  • 构造方法(略)
  • 其他方法(略)
  • 特有成员方法
方法说明
void newline()写一个文本行

十一、序列化流

1、什么是序列化

  • Java 提供了一种将对象持久化的方式。用一个字节序列表示一个对象,而字节序列可以写出到文件中。
  • 反之,字节序列可以从文件中读取到内存,重构对象,对它进行反序列化

2、前言

  • 参与序列化反序列化的对象,必须实现 Serializable 接口。这是一个标记接口,不需要重写任何方法。
  • jvm对实现了Serializable接口的类会自动生成一个序列化版本号。用于区别不同的
  • 一旦修改了类,就会重新生成版本号,这在实际应用中是不合适的,所以对于实现了Serializable接口的类,我们都会手动给一个固定的版本号。
  • 对于类中一些我们不愿意序列化的属性,可以使用transient关键字修饰,这样这个属性的数据就不会写道字节序列中去了。

3、ObjectOutputStream

处理流。

  • 构造方法
方法说明
ObjectOutputStream(OutputStream out);
  • 常用方法
方法说明
writeObject(Object obj);序列化对象

4、ObjectInputStream

处理流。

  • 构造方法
方法说明
ObjectInputStream(InputStream in);
  • 常用方法
方法说明
writeObject(Object obj);反序列化对象

十二、DataInputStream和DataOutputStream

处理流。数据字节输入流和数据字节输出流。对于Java中每一种类型的数据,它都有对应的方法读写。

  • 继承结构

    • DataOutputStream

    DataOutputStream

    • DataInputStream

DataInputStream

  • 对于写出数据,它会生成一个特定类型的文件;
  • 对于写入数据,你必须记得文件中的数据顺序,不然无法正确的读出数据;

十三、标准输出流

1、PrintStream

处理流。标准字节输出流,用于写数据的方法参数类型随意,输入什么写到文件就是什么。默认打印输出到控制台。

常用的 System.out.println(); 就是封装的这种流。

    @Test
    public void t7() throws FileNotFoundException {
        //一、使用默认的输出,效果是直接输出到控制台。
        System.out.println("输出到控制台");
        
        //二、创建自定义的输出流
        PrintStream ps = new PrintStream("C:\\Users\\86152\\Desktop\\printStream.txt");
        //设置使用自定义的输出流
        System.setOut(ps);
        //这时候就会输出到文件
        System.out.println("输出到文件");

    }
  • 继承结构

PrintStream

  • 构造方法
方法说明
PrintStream(File file)
PrintStream(OutputStream out)
PrintStream(String fileName)
  • 常用方法
方法说明
println(类型不定 x)输出完换行
print(类型不定 x)输出完不换行

2、PrintWriter

处理流。标准字符输出流。和PrintOutputStream类似。只不过PrintWriter继承自字符流,有字符流的特性;PrintOutputStream继承自字节流,有字节流的特性。

  • 继承结构

见目录第三大点。
tln(“输出到文件”);

}



- 继承结构

[外链图片转存中...(img-j8ODaQlo-1673330982824)]

- 构造方法

| 方法                          | 说明 |
| ----------------------------- | ---- |
| PrintStream(File file)        |      |
| PrintStream(OutputStream out) |      |
| PrintStream(String fileName)  |      |

- 常用方法

| 方法                | 说明         |
| ------------------- | ------------ |
| println(类型不定 x) | 输出完换行   |
| print(类型不定 x)   | 输出完不换行 |

### 2、PrintWriter

处理流。标准字符输出流。和PrintOutputStream类似。只不过PrintWriter继承自字符流,有字符流的特性;PrintOutputStream继承自字节流,有字节流的特性。

- 继承结构

见目录第三大点。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值