韩顺平Java37——IO流


IO流

  1.基本概念

  1.1文件

  1.2文件流

 流是针对内存来说的,输入输出也是以内存为基本点来说的

  2.常用的文件操作

  2.1创建文件相关方法

演示:

package newfile;

import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;

/**
 * @author 紫英
 * @version 1.0
 * @discription 创建文件
 */
public class FileCreate {

    private String parentPath;

    public static void main(String[] args) {

    }

    @Test
    public void create01() {
        //第一种方式 new File(String pathname) 根据路径构建一个File对线
        String filePath = "C:\\Users\\MI\\Desktop\\file01.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();//此时真正创建文件
            System.out.println("文件“file01.txt”创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Test
    public void create02() {
        //第二种方式 new File(File parent, String child)
        File parentFile = new File("C:\\Users\\MI\\Desktop");
        String fileName = "file02.txt";
        File file = new File(parentFile, fileName);//此时的file还只是一个对象
        try {
            file.createNewFile();//file.createNewFile()过后file02.txt文件才真正在硬盘中创建起来
            System.out.println("文件“file02.txt”创建成功");

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

    }
    @Test
    public void create03(){
        //第三种方式 new File(String parent, String child)
        parentPath = "C:\\Users\\MI\\Desktop";
        String fileName = "file03.txt";
        File file = new File(parentPath, fileName);
        try {
            file.createNewFile();
            System.out.println("文件“file03.txt”创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
可以看到确实在桌面上创建了三个文件

  2.2获取文件相关信息

 length是文件大小(字节)

演示:

package newfile;

import java.io.File;
import java.io.IOException;

/**
 * @author 紫英
 * @version 1.0
 * @discription 查看文件信息方法
 */
public class Fileinfo {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\MI\\Desktop\\file01.txt");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

//调用相应的方法,得到对应信息
        System.out.println("文件名字=" + file.getName());
//getName、getAbsolutePath、getParent、length、exists、isFile、 isDirectory
        System.out.println("文件绝对路径=" + file.getAbsolutePath());
        System.out.println("文件父级目录=" + file.getParent());
        System.out.println("文件大小(字节)=" + file.length());
        System.out.println("文件是否存在=" + file.exists());//T
        System.out.println("是不是一个文件=" + file.isFile());//T
        System.out.println("是不是一个目录=" + file.isDirectory());//F
    }
}

往文件里写了“666”

  2.3目录的操作和文件删除

注意在Java编程中目录也被当作一种文件

 演示:

package newfile;

import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;

/**
 * @author 紫英
 * @version 1.0
 * @discription 目录操作
 */
public class Directory {
    @Test
    public void m1() {
        //判断文件是否存在,如果存在就删除
        File file = new File("C:\\Users\\MI\\Desktop\\file01.txt");
        if (file.exists()) {
            if (file.delete()) {//既是条件又是语句
                System.out.println("删除成功!");
            } else {
                System.out.println("删除失败!");

            }
        } else {
            System.out.println("文件不存在!");
        }

    }

    @Test
    public void m2() {
        //判断目录是否存在,如果存在就删除
        //注意在Java编程中目录也被当作一种文件
        String dirPath = "C:\\Users\\MI\\Desktop\\aaa";
        File file = new File(dirPath);
        if (file.exists()) {
            if (file.delete()) {//既是条件又是语句
                System.out.println("删除成功!");
            } else {
                System.out.println("删除失败!");

            }
        } else {
            System.out.println("目录不存在!");
        }

    }

    @Test
    public void m3() {
        //判断目录是否存在,如果不存在就创建
        //想创建单级目录就用mkdir()
        // 多级用mkdirs() 比如"C:\\Users\\MI\\Desktop\\aaa\\bbb\\ccc"就会创建三级目录
        //单级目录不能用mkdirs()反之亦然

        String dirPath = "C:\\Users\\MI\\Desktop\\aaa";
        File file = new File(dirPath);
        if (file.exists()) {
            System.out.println("目录已存在");
        } else {
            if (file.mkdir()) {
                System.out.println("创建成功!");
            } else {
                System.out.println("创建失败!");

            }

            System.out.println("目录不存在!");
        }

    }
}

  3.IO流原理及流的分类

  3.1 IO流原理

 

  3.2流的分类

  •  注意:

  1.采用字符流传输的效率更高,但是在传输一些二进制文件(例如音频、视频)时使用字节流可以保证无损操作。

  2.文本文件使用字符流比较好

  3.这四个基本类都是抽象类

体系图:

 流与文件关系类比:

  4.常用类分析——InputSteam(字节输入流)

InputStream抽象类是所有类字节输入流的父类

  4.1FileInputStream

  • 构造方法

  •  方法

 两种read()方法演示:

package inputsteam;

import org.junit.jupiter.api.Test;

import java.awt.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @author 紫英
 * @version 1.0
 * @discription 两种read方法演示
 */
public class Fileinput {
    @Test
    public void m1() throws FileNotFoundException {
        //第一种方式——使用read一个字节一个字节地读取

        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\MI\\Desktop\\file02.txt");
        int readData = 0;
        try {
            while ((readData = fileInputStream.read()) != -1) {
        //read方法功能:读取单个字节,返回该字节的码值。如果读到文件末尾,返回-1
                System.out.print((char) readData);//循环输出单个字节 并转成char类型显示
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭文件流 释放资源
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
    @Test
    public void m2() throws FileNotFoundException {
        //第二种方式——使用read按照byte数组来读

        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\MI\\Desktop\\file02.txt");
        int readLen = 0;
        byte[] b = new byte[8];//创建一个8位数组一次性读八个
        try {
            while ((readLen=fileInputStream.read(b)) != -1) {
                //read(byte[] b)方法返回值——实际读取的字节数。如如果读取完毕,返回-1
                //这里用readLen来保存返回值,以确保字符串的顺利输出
                System.out.print(new String(b,0,readLen));//将数组封装成字符串输出
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭文件流 释放资源
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}

debug一下可以看到:第一次返回值是8,第二次是5

4.FileOutputStream

 将字符串转为byte[]数组的方法

 另一种写入方式

 注意:

 IO流实现文件拷贝

 演示:

package inputsteam;

import java.io.*;

/**
 * @author 紫英
 * @version 1.0
 * @discription 文件拷贝
 */
public class FileCopy {
    public static void main(String[] args) {
        int readLen;
        byte[] bytes = new byte[1024];
        FileInputStream in = null;//创建流对象
        FileOutputStream out = null;
        try {
            in = new FileInputStream("C:\\Users\\MI\\Desktop\\file02.txt");//文件写入对象
            out = new FileOutputStream("C:\\Users\\MI\\Desktop\\file02copy.txt");
            while ((readLen=in.read(bytes))!=-1){
                //一边读一边写
                out.write(bytes,0,readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭流释放资源
            try {
                in.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

注意:

FileWriter使用后一定要使用close()关闭,否则不会真正写入到文件

 

节点流和处理流

 节点流:针对某一种特定的数据源(比较底层)

处理流: 内部封装了一个对应的Reader或者Writer等父类的对象,可以对节点流进行操作,更加灵活

  • 修饰器设计模式代码模拟:
package bufferedreader01;

/**
 * @author 紫英
 * @version 1.0
 * @discription 修饰器设计模式模拟
 */
public class Bufferreader_ extends Reader_ {

    private Reader_ in; //封装一个Reader类型的对象

    public Bufferreader_(Reader_ in) {
        this.in = in;
    }

    @Override
    void read() {
        in.read(); //利用动态绑定机制
    }
}

abstract class Reader_ {
    abstract void read();
}

class FileReader_ extends Reader_ {

    @Override
    void read() {
        System.out.println("文件读取...");
    }
}

class StringReader_ extends Reader_ {

    @Override
    void read() {
        System.out.println("字符串读取...");
    }
}

测试:

package bufferedreader01;

/**
 * @author 紫英
 * @version 1.0
 * @discription
 */
public class Test {
    public static void main(String[] args) {
        Bufferreader_ bufferreader_ = new Bufferreader_(new FileReader_());
        bufferreader_.read();
        Bufferreader_ bufferreader_1 = new Bufferreader_(new StringReader_());
        bufferreader_1.read();
    }
}

 

字符处理流

   

 这里的外层流即处理流

  bufferedreader代码演示:

 bufferedwriter代码演示:

filewriter追加or覆盖: 

 字节处理流

 

 第二种构造方法说明一下:

size指定的是下图中byte [] buf的大小:可以看到默认是8192,如果加了就是按照指定大小,就是一次性读取多少个字节存到我们创建的byte[]类型数组中

如果buf的大小超过了我们创建的,比如指定buf大小为8,创建的为4,则先读取8个,分两次写入(一次写4个)

 

 因为按照这种传参方式,写入个数还是以我们创建的数组大小为准

 序列化和反序列化——对象流

  

 这两个类仍然属于处理流

 代码演示:

  • 写入:
package outputsteam;

import com.sun.org.apache.bcel.internal.generic.NEW;
import inputsteam.Dog;

import java.io.*;

/**
 * @author 紫英
 * @version 1.0
 * @discription 对象流实现序列化写入
 */
public class Objectoutputsteam01 {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("C:\\Users\\MI\\Desktop\\data.dat"));
        objout.writeInt(100);//int
        objout.writeChars("一给窝里giao");//string
        objout.writeObject(new Dog("旺财", 3));//Dog
        objout.close();//关闭流
        System.out.println("写入完毕!");

    }
}
 

注意写入的对象需要实现序列化接口否则会编译报错!








 

相关