IO流的入门讲解

一、File类

1、概念

        File 类是 java.io 包中唯一代表磁盘文件本身的对象,也就是说,如果希望在程序中操作文件和目录,则都可以通过 File 类来完成。File 类定义了一些方法来操作文件,如新建、删除、重命名文件和目录等。

        File 类不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。

2、构造方法

File 类提供了如下三种形式构造方法。

        File(String path):如果 path 是实际存在的路径,则该 File 对象表示的是目录;如果 path 是文件名,则该 File 对象表示的是文件。
        File(String path, String name):path 是路径名,name 是文件名。
        File(File dir, String name):dir 是路径对象,name 是文件名。

3、常用常量

File 类中有以下两个常用常量:

        public static final String pathSeparator:指的是分隔连续多个路径字符串的分隔符,Windows 下指;。例如java -cp test.jar;abc.jar HelloWorld。

        public static final String separator:用来分隔同一个路径字符串中的目录的,Windows 下指/。例如C:/Program Files/Common Files。

4、常用方法

public class Test02 {
    public static void main(String[] args) {
        String path = "D:/study/test"; // 指定文件所在的目录
        File f = new File(path, "test.txt"); // 建立File变量,并设定由f变量引用
        System.out.println("D:\\study\\test\\test.txt文件信息如下:");
        System.out.println("============================================");
        System.out.println("文件长度:" + f.length() + "字节");
        //检测实例对象代表的是否是文件
        System.out.println("文件或者目录:" + (f.isFile() ? "是文件" : "不是文件"));
        //检测实例对象代表的是否是目录
        System.out.println("文件或者目录:" + (f.isDirectory() ? "是目录" : "不是目录"));
        //检测实例对象代表的是否能可读取
        System.out.println("是否可读:" + (f.canRead() ? "可读取" : "不可读取"));
        //检测实例对象代表的是否能可写入
        System.out.println("是否可写:" + (f.canWrite() ? "可写入" : "不可写入"));
        //检测实例对象代表的是否是隐藏文件
        System.out.println("是否隐藏:" + (f.isHidden() ? "是隐藏文件" : "不是隐藏文件"));
        //检测实例对象代表的最后修改日期
        System.out.println("最后修改日期:" + new Date(f.lastModified()));
        //获取实例对象代表的文件名字
        System.out.println("文件名称:" + f.getName());
        //获取实例对象代表的文件的实际路径
        System.out.println("文件路径:" + f.getPath());
        //获取实例对象代表的文件的绝对路径
        System.out.println("绝对路径:" + f.getAbsolutePath());
    }
}

二、IO的基本概念

1、概念

        I和O,分别是Input和Output两个单词的缩写,Input是输入,Output是输出。
        流:是一种抽象概念,是对数据传输的总称.也就是说数据在设备间的传输称为流,流的本质是数据传输。IO流就是用来处理设备间数据传输问题的。常见的应用: 文件复制、文件上传、文件下载等。

2、分类

从数据的流向:

        输入流 : 从 硬盘读取数据到内存。
        输出流 : 从内存输出数据保存到硬盘中。

从传输的数据类型:

        字节流:以字节为单位进行数据的传输  --  可以处理任何的数据(视频 音乐 图片 文本 ....)。
        字符流:以字符为单位进行数据的传输  --  只能处理文本数据(txt 文件 html文件  java文件) 使用记事本软件正常打开并识别就是文本文件。

从功能上进行分类:

        节点流:负责传输数据的基本流。
        过滤流(处理流):增强节点流功能的流。

抽象上分为两类:

        堵塞式IO(BIO):同步并阻塞。服务器实现模式为一个连接一个线程,即用户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不做任何事情就会造成不必要的线程开销。

        非堵塞式io(NIO):同步非阻塞,服务器实现模式为一个线程处理多个请求连接,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询连接有I/O请求就进行处理。

        非堵塞式io(AIO): 异步非阻塞。服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS完成了再通知服务器应用去启动线程进行处理,一般适用于连接数较多且连接市场较长的应用。

三、字节流

1、分类       

         

        InputStream:这个抽象类是表示字节输入流的所有类的超类。
        OutputStream:这个抽象类是表示字节输出流的所有类的超类。

2、字节流的主要方法

OutputStream的主要方法

        public void write(byte[] b):将指定的字节输出流。
        public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
        public void close():关闭此输出流并释放与此流相关联的任何系统资源。

        public  void write(byte[] b):将 b.length个字节从指定的字节数组写入此文件输出流。
        public void write(byte[] b, int off, int len):将len个字节从位于偏移量 off的指定字节数组写入此文件输出流。
        public void write(int b):将指定的字节写入此文件输出流。
        public void close():关闭此文件输出流并释放与此流相关联的任何系统资源。

FileOutputStream(文件字节输出流):是 OutputStream 的子类。

        FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
        FileOutputStream(File file, boolean append):创建文件输出流以写入由指定的 File对象表示的文件。
        FileOutputStream(String name):创建文件输出流以指定的名称写入文件。
        FileOutputStream(String name, boolean append):创建文件输出流以指定的名称写入文件。

InputStream的主要方法

        public int read(byte[] b): 从输入流读取一个字节。
        public int read(): 从输入流读取一个字节。
        public void close() :关闭此输入流并释放与此流相关联的任何系统资源。

         public int read():从该输入流读取一个字节的数据。
        public int read(byte[] b):从该输入流读取最多 b.length个字节的数据为字节数组。
        public int read(byte[] b, int off, int len):从该输入流读取最多len字节的数据为字节数组。

        public void close():关闭此文件输入流并释放与此流相关联的任何系统资源。

FileInputStream(文件字节输入流):是 InputStream 的子类 。

        FileInputStream(File file):通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
        FileInputStream(String name):通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

注:进程结束的时候需手动关流,最好写在finally块中。

四、字符流

1、分类

        字符输出流:Writer
        字符输入流:Reader

2、主要方法

Writer的方法

        void    close():关闭流,先刷新。
        void    flush():刷新流。
        void    write(char[] cbuf):写入一个字符数组。
        void    write(char[] cbuf, int off, int len):写入字符数组的一部分。
        void    write(int c):写一个字符
        void    write(String str):写一个字符串
        void    write(String str, int off, int len):写一个字符串的一部分。

FileWriter文件字符输出流的构造方法:

        FileWriter(File file):给一个File对象构造一个FileWriter对象。
        FileWriter(File file, boolean append):给一个File对象构造一个FileWriter对象。
        FileWriter(String fileName):构造一个给定文件名的FileWriter对象。
        FileWriter(String fileName, boolean append):构造一个FileWriter对象。

Reader的主要方法:

        public int read(): 从输入流读取一个字符
        public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。每次最多读取cbuf.length个字符。返回实际读取的字符个数。如果已经到达流末尾,没有数据可读,则返回-1。
        public void close():关闭此流并释放与此流相关联的任何系统资源。

FileReader文件字符输入流的构造方法:

        FileReader(File file):创建一个新的 FileReader ,给出 File读取。
        FileReader(String fileName):创建一个新的 FileReader ,给定要读取的文件的名称。

五、缓冲流

1、概念

        缓冲流,也叫高效流。能够高效读写的数据流,能够转换编码的转换流,能够持久化存储对象的序列化对象等等。对文件或者其他目标频繁的操作,效率低,性能差。缓冲流目的是提高程序读取和写出的性能。缓冲流也分为字节缓冲流和字符缓冲流,其本质是通过缓冲区读写较少IO次数而提高效率的。

  • 字节缓冲流:BufferedInputStream,BufferedOutputStream
  • 字符缓冲流:BufferedReader,BufferedWriter

        缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO读取次数,从而提高读写的效率。

2、执行过程

  • 缓冲流把数据先写到缓冲区,默认情况下是当缓冲区满,或调用close,或调用flush这些情况才会把缓冲区的数据输出.

  • 关闭时,默认先关闭外面的流,再关闭内部的流。

3、拓展

字符流可以针对文档内容进行选择性读取或者写入

  • BufferedReader:public String readLine(): 读一行文字

  • BufferedWriter:public void newLine(): 写一行行分隔符,由系统属性定义符号

4、效率测试

 举例:不同方法,拷贝txt文件的速度,来测试效率

文件复制的步骤(不使用缓冲): 

1.创建一个字节输入流对象,构造方法中绑定要读取的数据源。2.创建一个字节输出流对象,构造方法中绑定要写入的目的地。 3.使用字节输入流对象中的方法read,读取文件。 4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中。 5.释放资源。 

文件复制的步骤(使用缓冲):

 1.创建字节缓冲输入流对象,构造方法中传递字节输入流。2.创建字节缓冲输出流对象,构造方法中传递字节输岀流。3.使用字节缓冲输入流对象中的方法read,读取文件。 4.使用字节缓冲输出流中的方法wite,把读取的数据写入到内部缓冲区中。 5.释放资源(会先把缓冲区中的数据,刷新到文件中)。

/** * 不使用缓冲字节输入输出流, * 一个一个字节的方式。 */
    public static void method1() throws IOException {
        FileInputStream fis = new FileInputStream("D:/study/doc/sde.txt");
        FileOutputStream fos = new FileOutputStream("D:/study/doc/copy1.txt");
        int len = 0;
        while ((len = fis.read()) != -1) {
            fos.write(len);
        }
        fis.close();
        fos.close();
    }/** * 不使用缓冲字节输入输出流, * 一次读取多个字节的方式。 */
    public static void method2() throws IOException {
        FileInputStream fis = new FileInputStream("D:/study/doc/sde.txt");
        FileOutputStream fos = new FileOutputStream("D:/study/doc/copy2.txt");
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        fis.close();
        fos.close();
    }
    /** * 使用缓冲字节输入输出流 */
    public static void method3() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/study/doc/sde.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/study/doc/copy3.txt"));
        byte[] bytes = new byte[1024];    int len = 0;    while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bos.close();
        bis.close();
    }
public class DemoEfficiency {
    public static void main(String[] args) throws IOException {
        // 方法1效率测试
        long method1StartTime = System.currentTimeMillis();
        method1();
        long method1EndTime = System.currentTimeMillis();
        System.out.println("使用方法1,文件复制耗时(毫秒):" + (method1EndTime - method1StartTime));
 
        // 方法2效率测试
        long method2StartTime = System.currentTimeMillis();
        method2();
        long method2EndTime = System.currentTimeMillis();
        System.out.println("使用方法2,文件复制耗时(毫秒):" + (method2EndTime - method2StartTime));
 
        // 方法3效率测试
        long method3StartTime = System.currentTimeMillis();
        method3();
        long method3EndTime = System.currentTimeMillis();
        System.out.println("使用方法3,文件复制耗时(毫秒):" + (method3EndTime - method3StartTime));
    }
}

控制台结果:

文件大小:20,867KB

运行程序,生成:copy1.txt、copy2.txt、copy3.txt三个文件

可以看出,使用缓冲字节输入输出流效率极高。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值