网络知识 娱乐 IO流:节点流和处理流详细归纳。

IO流:节点流和处理流详细归纳。

目录

一、节点流和处理流

二、处理流

1、BufferedReader 字符流

2、BufferedWriter 字符流

3、利用二者进行文件拷贝

4、BufferedInputStream 字节流

5、BufferedOutputStream 字节流

三、ObjectOutputStream、ObjectInputStream

 1、序列化和反序列化

 2、 ObjectOutputStream

 3、ObjectInputStream

 4、注意事项

 5、标准输入流和输出流

 四、转换流

 1、基本介绍

 2、把 FileInputStream 转成 InputStreamReader

  五、打印流

 1、PrintWriter

 2、PrintStream

  六、Properties类


一、节点流和处理流

(1)节点流可以从一个特定的数据源读写数据

(2)处理流(也叫包装流)是“连接” 在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能

(3)示意图

 

(4)两者的区别

  • 节点流是底层流/低级流,直接跟数据源相接
  • 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方
    便的方法来完成输入输出。
  • 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连

(5)处理流的功能

  • 性能的提高 : 主要以增加缓冲的方式来提高输入输出的效率
  • 操作的便捷 :处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

二、处理流

  •  BufferedReader 和 BufferedWriter 属于字符流,是按照字符来读取数据的
  • 关闭流时, 只需要关闭外层流即可
  • BufferedinputStream是字节流,在创建BufferedlnputStream 时,会创建一个内部缓冲区数组
  • BufferedOutputStream是字节流, 实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统

1、BufferedReader 字符流

public class BufferedReader_ {
    public static void main(String[] args) throws IOException {
        //文件路径
        String filePath = "d:\story.txt";

        //创建 BufferedReader 对象
        BufferedReader bur = new BufferedReader(new FileReader(filePath));

        //读取
        String line;//按行读取

        //当返回null时,表示文件读取完毕
        while ((line = bur.readLine()) != null){

            System.out.println(line);

        }

        //关闭流,这里注意,只需要关闭 BufferedReader ,因为底层会自动的去关闭节点流
        bufferedReader.close();
    }
}

2、BufferedWriter 字符流

public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        //文件路径
        String filePath = "d:\ok.txt";

        //创建 BufferedWriter
        //带true,表示追加
        BufferedWriter bur = new BufferedWriter(new FileWriter(filePath,true));

        bufferedWriter.write("hello,继续努力");

        bufferedWriter.newLine();//插入一个和系统相关的换行符

        bufferedWriter.write("hello,继续努力");

        bufferedWriter.newLine();//插入一个和系统相关的换行符

        bufferedWriter.write("hello,继续努力");


        //关闭外层流即可,传入的 new FileWriter(filePath),会在底层关闭
        bufferedWriter.close();


    }
}

3、利用二者进行文件拷贝

public class BufferedCopy_ {
    public static void main(String[] args) {
        //文件路径
        String srcFilePath = "d:\story.txt";
        String destFilePath = "d:\story2.txt";

        //分别创建对象
        BufferedReader br = null;
        BufferedWriter bw = null;
        
        //按行读取
        String line;

        try {
            //分别获取路径对象
            br = new BufferedReader(new FileReader(srcFilePath));
            bw = new BufferedWriter(new FileWriter(destFilePath));

            //readLine() 按行获取
            while ((line = br.readLine()) != null){

                //每读一行,就写入
                bw.write(line);

                //插入一个换行符
                bw.newLine();

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //两个流都要关闭
            try {
                if (br != null){
                    br.close();
                }
                if (bw != null){
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:

  • BufferedReader 和 BufferedWriter 是按字符操作
  • 不要去操作二进制文件[视频,声音,doc,PDF 等],可能会造成文件损坏

4、BufferedInputStream 字节流

5、BufferedOutputStream 字节流

public class BufferedCopy02 {
    public static void main(String[] args) {
        //文件路径
        String srcFilePath = "d:by.png";
        String destFilePath = "d:newby.png";

        //创建对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {

            //因为 FileInputStream 是 InputStream 的子类
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));

            //创建数组,以数组的方式读取和写入
            byte[] buff = new byte[1024];

            //文件长度
            int readLen = 0;

            //当返回-1 时,就表示文件读取完毕
            while ((readLen = bis.read(buff)) != -1){
                //边读取边写入
                bos.write(buff,0,readLen);

            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (bis != null){
                    bis.close();
                }
                if(bos != null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

三、ObjectOutputStream、ObjectInputStream

 1、序列化和反序列化

  • 序列化就是在保存数据时,保存数据的值和数据类型
  • 反序列化就是在恢复数据时,恢复数据的值和数据类型
  • 需要止某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
                   ①Serializable               ②Externalizable
  • 功能:提供了对基本类型或对象类型的序列化和反序列化的方法
  • ObjectOutputStream 提供序列化功能

  • ObjectInputStream 提供反序列化功能

2、 ObjectOutputStream

public class ObjectOutStream_ {
    public static void main(String[] args) throws Exception {

        //文件路径
        String filePath = "d:\data.txt";
        
        //创建对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据到 e:data.dat
        oos.writeInt(100); // int -> Integer (实现了 Serializable)

        oos.writeBoolean(true); //boolean -> Boolean (实现了 Serializable)

        oos.writeChar('a'); //char -> Character (实现了 Serializable)

        oos.writeDouble(9.5); //double -> Double (实现了 Serializable)

        oos.writeUTF("努力学习"); //String (实现了 Serializable)

        //保存一个dog对象
        oos.writeObject(new Dog("小白",10));

        oos.close();
        System.out.println("保存完毕");

    }
}

注意:序列化后,保存的文件格式,不是存文本的,而是按照它的格式来保存

3、ObjectInputStream

public class ObjectInputStream_ {
    public static void main(String[] args) throws Exception{

        //指定反序列化的文件路径
        String filePath = "d:\data.txt";
        
        //创建对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));

        //读取(反序列化)的顺序需要和保存数据(序列化)的顺序一致,否则会报异常
        System.out.println(ois.readInt());

        System.out.println(ois.readBoolean());

        System.out.println(ois.readChar());

        System.out.println(ois.readDouble());

        System.out.println(ois.readUTF());

        Object o = ois.readObject();
        System.out.println("运行类型=" + o.getClass());
        System.out.println("dog信息=" + o);


        //特别重要的细节:需要我们将Dog类的定义,放到可以引用的位置
        Dog dog = (Dog)o;
        System.out.println(dog.getName());


        //关闭流,关闭外层流即可,底层会关闭 FileInputStream 流
        ois.close();
    }
}

4、注意事项

  • 读写顺序要一致
  • 要求实现序列化或反序列化对象,需要实现 Serializable接口
  • 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
  • 序列化对象时, 默认将里面所有属性都进行序列化,但除了static关键字 或 transient关键字 修饰的成员
  • 序列化对象时,要求里面属性的类型也需要实现序列化接口
  • 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

5、标准输入流和输出流

public class InputAndOutput {
    public static void main(String[] args) {

        //System 类的 public final static InputStream in null;
        //System.in 编译类型  InputStream
        //System.in 运行类型 BufferedInputStream
        //表示标准输入 键盘
        System.out.println(System.in.getClass());

        //System.out ->  public static final PrintStream out = null;
        //编译类型 PrintStream
        //运行类型 PrintStream
        //表示标准输出 显示器
        System.out.println(System.out.getClass());
    }
}

四、转换流

 1、基本介绍

  • InputStreamReader : Reader的子类, 可以将InputStream(字节流)包
    装成Reader(字符流)

  • OutputStreamWriter : Writer的子类,实现将OutputStream(字节流)
    包装成Writer(字符流)

  • 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文
    问题,所以建议将字节流转换成字符流

  • 可以在使用时指定编码格式(比如 utf-8,gbk,gb2312等)

2、把 FileInputStream 转成 InputStreamReader

//指定编码gbk
InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"gbk");

//把InputStreamReader传入BufferedReader
BufferedReader br = new BufferedReader(isr);

//读取
String s = br.readLine();
System.out.println("读取内容="+s);

//关闭外层流
br.close();
//创建流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\a.txt") , "gbk" );

//写入
osw.write("hello,继续努力");

//关闭
osw.close();


五、打印流

1、PrintWriter

//PrintWriter pw= new PrintWriter(System.out);

PrintWriter pw = new PrintWriter(new FileWriter("e:\f2.txt"));

2、PrintStream

PrintStream out = System.out;
//在默认情况下,PrintStream输出数据的位置是标准输出,即显示器
//因为print底层使用的是write,所以我们可以直接调用write进行打印/输出
out.write("努力学习".getBytes());

out.close();
//我们可以去修改打印流输出的位置/设备
System.setOut(new PrintStream("e:\f1.txt"));

System.out.println("努力学习");

六、Properties类

(1)专门用于读写配置文件的集合类
        配置文件的格式 : 键=值

        注意 : 键值对不需要有空格,值不需要用引号引起来,默认类型是String

ip=192.168.0.13
user=root
pwd=12345

(2)Properties的常见方法

方法功能
load加载配置文件的健值对到Properties对象
list将数据显示到指定设备
getProperty(key)根据键获取值
setProperty(key , value)设健值对到Properties对象
store

将Properties中的键值对存储到配置文件,在idea 中,保存信息到配置文件,如果含有中文,会存储为unicode码 

//创建Properties对象
Properties pr = new Properties();

//加载指定配置文件
pr.load(new FileReader("src\mysql.properties"));

//把key-value显示控制台
pr.list(System.out);

//根据key获取对应的值
String user = pr.getProperty("user");
String pwd = pr.getProperty("pwd");

System.out.println("用户名="+user);
System.out.println("密码是="+pwd);
//使用Properties类来创建配置文件,修改配置文件内容
Properties pr = new Properties();

//创建
//1.如果该文件没有key就是创建
//2.如果该文件有key,就是修改
pr.setProperty("charset","utf8");

pr.setProperty("user","汤姆");//注意保存时,是中文的unicode码值

pr.setProperty("pwd","888888");

//将key-value存储在文件中即可
pr.store(new FileOutputStream("src\mysql2.properties"),null);