Java初学笔记--IO(4)

目录

高级流---对象流

对象输出流:(OOS)java.io.ObjectOutputStream

 对象输入流:(OPS)java.io.ObjectInputStream

高级流--字符流:

java.io.Reader 所有字符输出流的超类

转换流:

输出流

输入流

缓冲字符流

缓冲字符输出流-java.io.PrintWriter

缓冲字符输入流-java.io.BufferedReader


高级流---对象流

对象输出流:(OOS)java.io.ObjectOutputStream

  • 作用:将我们的java对象进行序列化
  • 序列化:将一个对象转换为一组可被传输或保存的字节。这组字节中除了包含对象本身的数据外,还会包含结构信息。
  • 序列化的意义:

实际开发中,我们通常会将对象
- 写入磁盘,进行长久保存
- 在网络间两台计算机中的java间进行传输
无论是保存在磁盘中还是传输,都需要将对象转换为字节后才可以进行。

Serializable关键字:

序列化对象时要求该对象对应的类必须实现接口:java.io.Serializable(Person类需要继承Serializable接口) 如果写出的对象对应的类没有实现该接口,那么writeObject会抛出下面异常 java.io.NotSerializableException

package io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
 * 对象流
 * 使用对象输出流完成对象序列化操作并最终保存到文件prison.obj中
 */
public class OOSDemo {
    public static void main(String[] args) throws IOException {
        String name = "小白熊";
        int age = 15;
        String gender = "女";
        String[] otherInfo = {"白","喜欢吃鱼","捕鱼技术好","来自北极"};
        Person p = new Person(name,age,gender,otherInfo);
        FileOutputStream fos = new FileOutputStream("person.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(p);
        System.out.println("对象写出完毕");
        oos.close();
    }

}
//序列化对象时要求该对象对应的类必须实现接口:java.io.Serializable(Person类需要继承Serializable接口)
//如果写出的对象对应的类没有实现该接口,那么writeObject会抛出下面异常
//java.io.NotSerializableException

--------------------
package io;

import java.io.Serializable;
import java.util.Arrays;

/**
 * 使用当前类测试对象流的读写操作
 */
public class Person implements Serializable {

        private String name;
        private int age;
        private String gender;
        private String[] otherInfo;

    public Person(String name, int age, String gender, String[] otherInfo) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.otherInfo = otherInfo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String[] getOtherInfo() {
        return otherInfo;
    }

    public void setOtherInfo(String[] otherInfo) {
        this.otherInfo = otherInfo;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", otherInfo=" + Arrays.toString(otherInfo) +
                '}';
    }

}

 对象输入流:(OPS)java.io.ObjectInputStream

  • 作用:将java对象进行反序列化
  • 反序列化

transient关键字:

当一个属性被transient关键字修饰后,该对象在进行序列化时,转换出来的字节中是不包含该属性的。忽略不必要的属性可以达到对象"瘦身"的操作。

对象瘦身可以在对象持久化时减少磁盘开销。在进行传输时可以缩短传输速度。

如果该对象不需要序列化,那么该关键字不发挥其他任何效果

 

 序列化时不包含otherInfo属性,并且反序列化时该属性值为null:

package io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
 * 对象输入流,用来进行对象反序列化
 */
public class OISDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //读取person.obj文件并将其中保存的数据进行反序列化
        FileInputStream fis = new FileInputStream("person.obj");
        ObjectInputStream ois = new ObjectInputStream(fis);

        Person person = (Person) ois.readObject();
        System.out.println(person);

        ois.close();

    }
}

高级流--字符流:

  • java将流按照读写单位划分为字节流与字符流.

  • java.io.InputStream和OutputStream是所有字节流的超类

  • 而java.io.Reader和Writer则是所有字符流的超类,它们和字节流的超类是平级关系.

  • Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.

  • 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成.

  • 字符流都是高级流

常用方法:

  • void write(int c):写出一个字符,写出给定int值”低16”位表示的字符。

  • void write(char[] chs):将给定字符数组中所有字符写出。

  • void write(String str):将给定的字符串写出

  • void write(char[] chs,int offset,int len):将给定的字符数组中从offset处开始连续的len个字符写出

java.io.Reader 所有字符输出流的超类

  • int read():读取一个字符,返回的int值“低16”位有效。当返回值为-1时表达流读取到了末尾。
  • int read(char[] chs):从该流中读取一个字符数组的length个字符并存入该数组,返回值为实际读取到的字符量。当返回值为-1时表达流读取到了末尾。

转换流:

  • java.io.InputStreamReader和OutputStreamWriter是常用的字符流的实现类。实际开发中我们不会直接操作他们,但是他们在流连接中是必不可少的一环。

流连接中的作用

  • 衔接字节流与其他字符流

  • 将字符与字节相互转换

意义

        实际开发中我们还有功能更好用的字符高级流.但是其他的字符高级流都有一个共通点:不能直接连接在字节流上.而实际操作设备的流都是低级流同时也都是字节流.因此不能直接在流连接中串联起来.转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上.在流连接中起到"转换器"的作用(负责字符与字节的实际转换)

输出流

构造器

  • OutputStreamWriter(OutputStream out,Charset cs) 基于给定的字节输出流以及字符编码创建OSW
  • OutputStreamWriter(OutputStream out) 该构造方法会根据系统默认字符集创建OSW
package io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;

/**
 * 转换流写出文本数据
 */
public class OSWDemo {
    public static void main(String[] args) throws IOException {
        //向文件osw.txt中写出文本数据
        FileOutputStream fos = new FileOutputStream("osw.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);

        osw.write("一句话");
        osw.write("第二句话");
        System.out.println("写出完毕");
        osw.close();

    }
}

输入流

构造器

  • InputStreamWriter(InputStream in,Charset cs) 基于给定的字节输入流以及字符编码创建当前转换流
  • InputStreamWriter(InputStream in) 该构造方法会根据系统默认字符集创建当前转换流
package io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * 使用转换流读取文本数据
 */
public class ISRDemo {
    public static void main(String[] args) throws IOException {
        //将osw.txt文件中的文本信息读取回来
        FileInputStream fis = new FileInputStream("osw.txt");
        InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
        //00000000 00000000 10011101 01110010
        int d;
        while(( d = isr.read()) != -1) {
            System.out.print((char) d);
        }
        isr.close();
    }
}

缓冲字符流

缓冲字符输出流-java.io.PrintWriter

  • java.io.BufferedWriter和BufferedReader

  • 缓冲字符流内部也有一个缓冲区,读写文本数据以块读写形式加快效率.并且缓冲流有一个特别的功能:可以按行读写文本数据.缓冲流内部维护一个char数组默认长度8192.以块读写方式读写字符数据保证效率

  • java.io.PrintWriter具有自动行刷新的缓冲字符输出流,实际开发中更常用.它内部总是会自动连BufferedWriter作为块写加速使用.

特点

  • 可以按行写出字符串

  • 具有自动行刷新功能

对文件写操作的构造器

PrintWriter(File file)

PrintWriter(String path)

还支持指定字符集

PrintWriter(File file,String csn)

PrintWriter(String path,String csn)

上述构造器看似PW可以直接对文件进行操作,但是它是一个高级流,实际内部会进行流连接:

this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),false);

其他构造器

PritWriter(Writer writer) 将当前实例化的PrintWriter链接在指定的字符输出流上

PrintWriter(OutputStream out) 将当前实例化的PrintWriter链接在指定的字节输出流上 由于除了转换流外的其他字符流都不能直接连在字节流上,因此这个构造器内部会自动链接在

BufferedWriter上 并且让BufferedWriter链接在转换流OutputStream上,最后再让转换流链接再指定的字节输出流上

package io;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 *  自行完成流连接向文件写出字符串
 */
public class PWDemo2 {
    public static void main(String[] args) throws FileNotFoundException {
        //负责:将写出的字节写入到文件中
        FileOutputStream fos = new FileOutputStream("pw2.txt");
        //负责:将写出的字符全部转换为字节(可以按照指定的字符集转换)
        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        //负责:块写文本数据(攒够8192个字符一次性写出)
        BufferedWriter bw = new BufferedWriter(osw);
        //负责:按行写出字符串
        PrintWriter pw = new PrintWriter(bw);

        pw.println("这是第一句话");
        pw.println("这是另一句话");

        System.out.println("写出完毕");
        pw.close();
    }
}

自动行刷新

PrintWriter支持自动行刷新,每当我们调用println方法写出一行内容后自动flush一次。

对应的构造器
PritWriter(Writer writer,boolean autoflush)
如果第二个参数为true则开启自动行刷新 
package io;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/**
 * 实现一个简易的记事本工具
 * 利用流连接
 * 在文件输出流上最终链接到PrintWriter上。
 * 然后将用户在控制台上输入的每一行字符串都可以按行写入到对应的文件中。
 * 当用户在控制台上单独输入"exit"时程序退出。
 */
public class AutoFlushDemo {
    public static void main(String[] args) throws FileNotFoundException {
        //负责:将写出的字节写入到文件中
        FileOutputStream fos = new FileOutputStream("note.txt");
        //负责:将写出的字符全部转换为字节(可以按照指定的字符集转换)
        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        //负责:块写文本数据(攒够8192个字符一次性写出)
        BufferedWriter bw = new BufferedWriter(osw);
        //负责:按行写出字符串
        PrintWriter pw = new PrintWriter(bw,true);//开启自动行刷新

        Scanner scanner = new Scanner(System.in);
        System.out.println("请开始输入内容,单独输入exit退出");
        while(true){
            String line = scanner.nextLine();
            //String可以忽略大小写比较字符串内容:equalsIgnoreCase
            if("exit".equalsIgnoreCase(line)){
                break;
            }
            pw.println(line);//每当println后自动flush。注意:print方法并不会自动flush
        }
        System.out.println("再见!");
        pw.close();
    }
}

缓冲字符输入流-java.io.BufferedReader

缓冲字符输入流内部维护一个默认8192长度的char数组,总是以块读取文本数据保证读取效率。

缓冲输入流提供了一个按行读取文本数据的方法

String readLine() 返回一行字符串。方法内部会连续扫描若干个字符,直到遇到换行符为止,将换行符之前的内容以一个字符串形式返回。 返回的字符串中不含有最后的换行符。 返回值有三种情况: 1:正常一行内容 2:空字符串。当读取了一个空行时(这一行只有一个换行符)。 3:null。当流读取到了末尾时。

当我们第一次调用readLine()时,流并不是只读取了一行字符串,而是先进行块读操作(一次性读取8192个字符并转入到内部的char数组中),然后扫描内部的char数组,然后将第一行字符串返回。第二次调用后再继续扫描后去的内容以此类推。

package io;

import java.io.*;
/**
 * 使用缓冲字符输入流读取文本数据
 */
public class BRDemo {
    public static void main(String[] args) throws IOException {
        //将当前源代码输出到控制台上
        /*
            1:创建文件输入流读取当前源代码文件
            2:进行流连接最终链接到BufferedReader上
            3:读取每一行字符串并输出到控制台上
         */
        FileInputStream fis = new 										         FileInputStream("路径");
        InputStreamReader isr = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(isr);

        String line;
        while((line = br.readLine())!=null) {
            System.out.println(line);
        }
        br.close();
    }
}

玫瑰玫瑰玫瑰 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值