韩顺平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 inputsteam.Dog;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * @author 紫英
 * @version 1.0
 * @discription 对象流实现序列化写入
 */
public class Objwrite {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C:\\Users\\MI\\Desktop\\data.data"));
        objectOutputStream.writeInt(100);
        objectOutputStream.writeBoolean(true);
        objectOutputStream.writeUTF("卡机还是给丢啊伟大hi");  这里注意如果读取用的readUTF写入最好也用 不然容易出错
        objectOutputStream.writeObject(new Dog("旺财",2));
        objectOutputStream.close();
        System.out.println("序列化写入完毕!");
    }
}

 

 

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

  • 读取:
package inputsteam;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * @author 紫英
 * @version 1.0
 * @discription 对象流实现反序列化读取
 */
public class Objin {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("C:\\Users\\MI\\Desktop\\data.data"));
        System.out.println(objectInputStream.readInt());
        System.out.println(objectInputStream.readBoolean());
        String s = null;
        s = objectInputStream.readUTF();
        System.out.println(s);
        Object dog = objectInputStream.readObject();

        System.out.println(dog);
        objectInputStream.close();
        System.out.println("反序列化读取完毕!");


    }
}

 

 细节:

 

 

 

 说明 3)

private static final long serialVersionUID = 1L; 加了这个在对类进行修改后序列化的时候不会认为是一个新类,而会认为是当前类的不同版本

5)

如果一个类中有一个属性是另一个类,则要求另一个类也要实现序列化接口

 

 标准输入输出流

 

 

 

 

 

 

 

 

 转换流

 

 ANSI是国标码 对应到中文系统是GBK

 

 

 reader代码演示:

 

writer代码演示:

 

 

打印流

注意打印流只有输出流

字节打印流:

 

 

 

字符打印流:

 代码演示:

 

 

 

 

 

 

 

 

 

 

posted @ 2022-01-28 01:08  紫英626  阅读(43)  评论(0编辑  收藏  举报

紫英