IO字节流

File

java.io.File[C] - File包含文件或者文件夹[目录directory]

作用:它是用来操作File本身的信息的[比如支持File的创建,删除,获取File的名称,获取File的路径等信息]

它并不支持文件里面的内容的读写操作[文件内中的内容的读写操作是交给IO流去实现]

支持本地File以及远程File的操作的.

File对象 - Java程序将磁盘上的文件加载内存中然后映射到File对象上 - File是内存中的磁盘上的映射.

构造方法

File(String path);//利用一个路径来构建一个File实例.这个路径可以是文件的路径,也可以是文件夹的路径

路径分成相对路径和绝对路径.

绝对路径 - windows操作系统是以盘符号开头的路径,Linux/mac以/开头的路径

相对路径 - 不是以盘符或者/开头的路径

常用方法

  1. boolean createNewFile();//创建一个文件,该方法是要抓取异常的.

  2. String getAbsolutePath();//获取该File的绝对路径

  3. String getName();//获取File的名称

  4. String getParent();//获取该File的父目录的绝对路径

  5. boolean exists();//判断File是否存在

  6. boolean delete();//删除文件或者文件夹

    6-1. 文件是否可以直接被删除的

    6-2. 如果是空目录 - 直接删除的

    6-2. 如果是非空目录 - 将会删除失败 - 递归算法来实现的.

  7. boolean mkdir();//创建单层次的目录,一次只能创建一个目录

  8. boolean mkdirs();//既可以创建单层次的目录,又可以同时创建多个不存在的目录.

  9. boolean isFile();//判断File实例是否为文件的实例

  10. boolean isDirectory();//判断file实例是否为文件夹的实例

  11. String[] list();//返回的是File的名称,返回的是传入的路径下的第一层的内容.

  12. File[] listFiles();//返回的第一层的File实例

  13. File[] listFiles(FilenameFilter filter);//找到指定后缀/前缀/满足条件的这么一个File实例

练习

  1. 传入一个目录,输出这个目录下的所有的内容.

    public class Test {
        public static void main(String[] args) {
            findAllFile("C:/Users/ASUS/Desktop/img");
        }
    
        private static void findAllFile(String path) {
            File file = new File(path);
    
            if (!file.exists()){
                System.out.println(file + "不存在,请给我一个正确的目录好吗?");
            }
    
            File[] files =file.listFiles();
    
            for (File f : files) {
                if (f.isFile()){              //如果是文件 - 直接输出名称
                    System.out.println(f.getName());
                }else if (f.isDirectory()){   //如果是文件夹 - 输出绝对路径
                    System.out.println(f.getAbsoluteFile());
                    //findAllFile(f.getAbsolutePath());
                }
            }
        }
    }
    

练习

②删除一个非空目录

public class Test {
    public static void main(String[] args) {
        findAllFile("C:/Users/ASUS/Desktop/img");
    }

    private static void findAllFile(String path) {
        File file = new File(path);

        if (!file.exists()){
            System.out.println(file + "不存在,请给我一个正确的目录好吗?");
        }

        File[] files =file.listFiles();

        for (File f : files) {
            if (f.isFile()){              //如果是文件 - 直接输出名称
                System.out.println(f.getName());
            }else if (f.isDirectory()){   //如果是文件夹 - 输出绝对路径
                System.out.println(f.getAbsoluteFile());
                //findAllFile(f.getAbsolutePath());
            }
        }
    }
}

IO流

流是一种抽象概念,它代表了数据的无结构化传递按照流的方式[数据在传输之前,需要进行转换,转换成无结构的字节/字符序列]进行有序的输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入(Input)输出(Output)

在这里插入图片描述

流想象成是数据传输的那个管道
磁盘中数据加载/读入到内存中 - 输入

在这里插入图片描述

java内存中数据写出去到磁盘中 - 输出

在这里插入图片描述

流的分类

  1. 按照流的方向 - 输入流和输出流

  2. 按照流的读取的单位不同 - 字节流[按照单个字节单个字节进行读写,文本文件或者二进制文件]和字符流[单个字符进行读写,只能操作文本字符文件]

  3. 按照流的功能 - 节点流[基础流]和拓展流[过滤流或者包装流] - 采用了”装饰器设计模式思想”

    **节点流才具备真正操作文件的能力.**拓展流只是让流的功能更加强大而已,拓展流脱离了节点流的话,那么是不允许的.

    拓展流的使用必须要建立在节点流的基础之上.

字节流

字节输入流

  1. java.io.InputStream[C] - 字节输入流的顶级的抽象的父类
    • java.io.FileInputStream[C] - 文件字节输入流 - 操作文件的读操作. - 典型的节点流
    • java.io.ObjectInputStream[C] - 操作对象类型的字节输入流 - 典型的包装流
    • java.io.FilterInputStream[C] - 过滤流
      • java.io.BufferedInputStream[C] - 带缓存功能的流 - 缓冲流
      • java.io.DataInputStream[C] - 操作基本数据类型的字节输入流

字节输出流

java.io.OutputStream[C] - 字节输出流的顶级的抽象的父类

  • java.io.FileOutputStream[C] - 文件字节输出流 - 操作文件的写操作. - 典型的节点流
  • java.io.ObjectOutputStream[C] - 操作对象类型的字节输出流 - 典型的包装流
  • java.io.FilterOutputStream[C] - 过滤流
    • java.io.BufferedOutputStream[C] - 带缓存功能的流 - 缓冲流
    • java.io.DataOutputStream[C] - 操作基本数据类型的字节输出流

InputStream常用方法

  1. void close();//关闭流,流本身就是一个对象[占内存 - 昂贵的资源]
  2. abstract int read();//单个字节单个字节的读取,如果读不到,返回-1
  3. int read(byte[] b);//从输入流读取一些字节数,并将它们存储到缓冲区 b

OutputStream常用方法

  1. void close();//关闭
  2. abstract void write(int b);将指定的字节写入此输出流。
  3. void write(byte[] b, int off, int len);

IO流的编程步骤

  1. 确定流 - 选什么流
  2. 确定源头和目标
  3. 循环读取,循环写出 - while
  4. 关闭流

缓冲流BufferedInputStream

在它出来之前,可以可以单个字节单个字节进行读写操作 - 弊端:java程序和磁盘的IO交互比较频繁,性能就会低下.

采取了自定义的数组的方式.从磁盘文件中读取一定数量的字节先放入到缓冲数组中.然后再从缓冲数组中一次性写出到磁盘中.

减少了java程序和磁盘的IO交互 - 性能提高.

JDK中发现了这点,提供了缓冲流BufferedInputStream

private static int DEFAULT_BUFFER_SIZE = 8192;//默认的容量8kb

protected volatile byte buf[];//内置的缓冲区

public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}

public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
 throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];//初始化内置的缓冲区数组 - 大小是8kb
}

底层利用了”装饰器”思想.这个流属于包装流,拓展流,过滤流,本身不具备真正的文件的读写能力.

构建带缓冲功能的流,必须要以节点流作为支撑
构架一个带缓冲功能的能够读取文件的字节输入流

BufferedInputStream in = new BufferedInputStream(new FileInputStream(“路径”));

BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(“路径”));

缓冲数组

BufferedInputStream本身已经在底层定义了8kb的字节数组,那么为什么程序中还自定义了一个3kb的字节数组[可以不定义,read()方法],自定义的byte[]和内置的byte[]各自的作用是什么?

内置的8kb的byte[] - 在一开始或者后面空闲的时候,由JVM去装载磁盘上的数据,提前放入到这个内置的byte[]中的.

/**
 * 本类用来演示: 缓冲流
 */
public class BufferDemo {
    public static void main(String[] args) {
        BufferedInputStream in = null;

        BufferedOutputStream out = null;

        try {
            //jvm加载磁盘上的数据到内置的byte[]中
            in = new BufferedInputStream(new FileInputStream("src/sth/aistar/day13/fast.gif"));
            out = new BufferedOutputStream(new FileOutputStream("src/stu/aistar/day13/fast_副本.gif"));

            //自定义一个byte[]
            //真正的读
            byte[] buf = new byte[3*1024];

            int len = -1;

            while(true){
                len = in.read(buf);
                if(len==-1)
                    break;
                out.write(buf,0,len);
            }
            System.out.println("文件拷贝成功!");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

读过程

  1. 当初始化好缓冲流之后,jvm会立即读取磁盘中的数据到内置的缓冲数组中
  2. 当程序中循环读取到的时候 len = in.read(buf); = 程序是直接从内置的缓冲区[内置的缓冲数组中]
  3. 一旦内置的数组中的8kb数据被取完,那么jvm在空闲的时候,继续加载文件中下一个8kb的字节到内置的缓冲区.

语法糖

jdk7.0提供的写法

作用 - 把流的关闭交给JVM
try(资源对象的声明1;资源对象的声明2){

}catch(..){
...
}
/**
 * 本类用来演示: 语法糖 - JVM去关闭流
 */
@SuppressWarnings("all")
public class StreamAutoCloseDemo {
    public static void main(String[] args) {
        //自动关闭这些资源
        try(BufferedInputStream in = new BufferedInputStream(new FileInputStream("src/stu/aistar/day13/fast.gif"));
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("src/stu/aistar/day13/fasts.gif"))){
            //自定义一个byte[]
            byte[] buf = new byte[3*1024];

            int len = -1;

            while(true){
                len = in.read(buf);
                if(len==-1)
                    break;
                out.write(buf,0,len);
            }
            System.out.println("文件拷贝成功!");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ObjectInputStream/ObjectOutputStream

操作对象类型的字节输入流和字节输出流,拓展流,必须要以节点流作为支撑

构建一个能够读写对象类型的文件字节输入流/输出流
ObjectInputStream in = new ObjectInputStream(new FileInputStream("path"))
构建一个能够读写对象类型的并且带缓冲功能的文件字节输入流
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream("path")));

利用”装饰器”思想,我们构建出功能更加强大的流,但是又不会对原来的流的结构产生任何影响.

对象的序列化

也叫做 - 数据的持久化的过程. - 把内存中的java对象存储到磁盘的文件的过程.

注意点:

  1. 如果保存的是单个对象,这个对象的实体类必须要实现java.io.Serializable序列化接口

    如果没有实现这个接口,进行序列化的时候,抛出一个java.io.NotSerializableException不可被序列化的异常

  2. 保存的是数组/集合,那么集合中的每个对象对应的实体类也是需要实现这个序列化的接口

关于追加写入,设置FileOutputStream(String path,boolean append);//append设置true,但是不支持分批次读取.

对象的反序列化

生任何影响.

对象的序列化

也叫做 - 数据的持久化的过程. - 把内存中的java对象存储到磁盘的文件的过程.

注意点:

  1. 如果保存的是单个对象,这个对象的实体类必须要实现java.io.Serializable序列化接口

    如果没有实现这个接口,进行序列化的时候,抛出一个java.io.NotSerializableException不可被序列化的异常

  2. 保存的是数组/集合,那么集合中的每个对象对应的实体类也是需要实现这个序列化的接口

关于追加写入,设置FileOutputStream(String path,boolean append);//append设置true,但是不支持分批次读取.

对象的反序列化

java对象已经存储到磁盘的文件中,希望再从文件中将这些对象数据加载到内存中[映射到java对象上].

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值