java_day16_IO、序列化

一、IO流

IO流划分

IO流【输入输出流】:
    按照流向划分:
        输入流:外部数据 -> java程序
        输出流:java程序 -> 外部数据


按照数据类型划分【根据使用记事本打开是否能够看懂来决定】
字节流【万能流】:
    字节输入流:
        InputStream【抽象类】
            - FileInputStream【实现子类】【普通字节输入流】
            - BufferedInputStream【字节缓冲输入流】

    字节输出流:
        OutputStream【抽象类】
            - FileOutputStream【实现子类】【普通字节输出流】
            - BufferedOutputStream【字节缓冲输出流】

字符流:
    字符输入流:
        Reader【抽象类】
            - InputStreamReader【具体实现子类】【普通字符输入流】
                - FileReader【继承自InputStreamReader】
            - BufferedReader 【字符缓冲输入流】

    字符输出流:
        Writer【抽象类】
            - OutputStreamWriter【具体实现子类】【普通字符输出流】
                - FileWriter【继承自OutputStreamWriter】
            - BufferedWriter【字符缓冲输出流】

一、字节流

1、字节输入流

普通字节输入流

字节流【万能流】:
字节输入流:
    InputStream(抽象类)
        - FileInputStream(实现子类)

    FileInputStream:
        构造方法:
            FileInputStream(File file)
            FileInputStream(String name)
        成员方法:
            public int read()
            public int read(byte[] b)

代码案例:

public class FileInputStreamDemo1 {
    public static void main(String[] args) throws Exception {
//        FileInputStream fis = new FileInputStream(new File("java/src/com/shujia/day16/a1.txt"));
        FileInputStream fis = new FileInputStream("java/src/com/shujia/day16/a1.txt");

        //public int read() 一次只读取一个字节
        // 如果没有读到数据,返回-1
//        System.out.print((char)fis.read());
//        System.out.print((char)fis.read());
//        System.out.print((char)fis.read());
//        System.out.print((char)fis.read());
//        System.out.print((char)fis.read());
//        System.out.print((char)fis.read());
//        System.out.print((char)fis.read());
//        int i = 0;
//        while ((i = fis.read()) != -1) {
//            System.out.print((char) i);
//        }

        //public int read(byte[] b) 一次读取一个字节数组
        //创建一个字节数组,用作接收读取到的字节
        byte[] bytes = new byte[7];
        int length = 0;
        while ((length = fis.read(bytes))!=-1){
            //读取到的字节在字节数组中
            //返回的是实际读取到的字节数
            //将字节数组转字符串
            String s = new String(bytes,0,length);
            System.out.print(s);
        }




        // 释放资源
        fis.close();
    }
}

字节缓冲输入流

InputStream:
    FileInputStream【普通的字节输入流】:
    BufferedInputStream【字节缓冲输入流】:

代码案例:

public class BufferedInputStreamDemo1 {
    public static void main(String[] args) throws Exception {
        //BufferedInputStream(InputStream in)
        //创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("java/src/com/shujia/day16/a1.txt"));

        // 一次读一个字节
//        int i = 0;
//        while ((i=bis.read())!=-1){
//            System.out.print((char) i);
//        }

        // 一次都一个字节数组
        byte[] bytes = new byte[1024];
        int length = 0;
        while ((length = bis.read(bytes)) != -1) {
            String s = new String(bytes, 0, length);
            System.out.print(s);
        }


        //释放资源
        bis.close();
    }
}

2、字节输出流

普通字节输出流

字节流【万能流】:
    字节输出流:
       OutputStream(抽象类)
          - FileOutputStream(实现子类)

  FileOutputStream:
    构造方法:
        FileOutputStream(File file)
        FileOutputStream(String name)

代码案例:

public class FileOutputStreamDemo1 {
    public static void main(String[] args) throws Exception{
        // FileOutputStream(File file) 将目标文件封装成File对象
        // 若目标文件不存在,则会自动创建
//        FileOutputStream fos = new FileOutputStream(new File("java/src/com/shujia/day16/a1.txt"));

        //FileOutputStream(String name)
        FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt");


    }
}
public void write(int b)
public void write(byte[] b)
public void write(byte[] b,int off,int len)

代码案例:

public class FileOutputStreamDemo2 {
    public static void main(String[] args) throws Exception{
//        FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt");
        //public FileOutputStream(String name, boolean append)
        FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt", true);

        //public void write(int b) 写一个ASCII码值
//        fos.write(97);

        // public void write(byte[] b) 写一个字节数组到文件中
//        byte[] bytes = {97,98,99,100,101,102};
//        fos.write(bytes);


        //public void write(byte[] b,int index,int len)
//        fos.write(bytes,2,3);

        fos.write("\r\n".getBytes());
        fos.write("李刚真帅!".getBytes());

        //释放资源
        fos.close();
    }
}

字节缓冲输出流

OutputStream:
    FileOutputStream【普通的字节输出流】:
    BufferedOutputStream【字节缓冲输出流】:

代码案例:

public class FileOutputStreamDemo2 {
    public static void main(String[] args) throws Exception{
//        FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt");
        //public FileOutputStream(String name, boolean append)
        FileOutputStream fos = new FileOutputStream("java/src/com/shujia/day16/a1.txt", true);

        //public void write(int b) 写一个ASCII码值
//        fos.write(97);

        // public void write(byte[] b) 写一个字节数组到文件中
//        byte[] bytes = {97,98,99,100,101,102};
//        fos.write(bytes);


        //public void write(byte[] b,int index,int len)
//        fos.write(bytes,2,3);

        fos.write("\r\n".getBytes());
        fos.write("李刚真帅!".getBytes());

        //释放资源
        fos.close();
    }
}

二、字符流

1、字符输入流

普通字符输入流

字符流:
   字符输入流:
       Reader【抽象类】
           - InputStreamReader【具体实现子类】
               - FileReader【继承自InputStreamReader】

   InputStreamReader:
        构造方法:
            InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。
            InputStreamReader(InputStream in, String charsetName) 创建一个使用命名字符集的InputStreamReader。
        成员方法:
            public int read()
            public int read(char[] cbuf)

代码案例:

public class InputStreamReaderDemo1 {
    public static void main(String[] args) throws Exception {
//        InputStreamReader isr = new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/a3.txt"));
        //InputStreamReader(InputStream in, String charsetName)
        InputStreamReader isr = new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/a3.txt"), "GBK");


        // public int read() 一次都一个字符
//        System.out.print((char) isr.read());
//        System.out.print((char) isr.read());
//        int i = 0;
//        while ((i = isr.read()) != -1) {
//            System.out.print((char) i);
//        }

        //public int read(char[] cbuf) 一次读取一个字符数组
        char[] chars = new char[1024];
        int length = 0;
        while ((length= isr.read(chars))!=-1){
            String s = new String(chars, 0, length);
            System.out.print(s);
        }


        // 释放资源
        isr.close();
    }
}

用上面的InPutStreamReader创建字符输入流对象,还要传入一个字节输入流对象,挺麻烦的,java还有一个类描述字符输入流,FileReader,使用该类创建字符输入流对象只用传文件地址就行了
FileReader:

字符缓冲输入流

字符输出流:
    Writer【抽象类】
       - OutputStreamWriter【具体实现子类】
            - FileWriter【继承自OutputStreamWriter】
       - BufferedWriter【字符缓冲输出流】

    BufferedReader 【字符缓冲输入流】:
        构造方法:
            BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。
        特殊功能:
            public String readLine() 一次读取文本文件内容的一行, 不会读取换行符

代码案例:

public class BufferedReaderDemo1 {
    public static void main(String[] args) throws Exception {
        //创建字符缓冲输入流对象
//        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/b3.txt")));
        BufferedReader br = new BufferedReader(new FileReader("java/src/com/shujia/day16/b3.txt"));

        //一次读一个字符
//        int i = 0;
//        while ((i=br.read())!=-1){
//            System.out.print((char) i);
//        }

        //一次读一个字符数组
//        char[] chars = new char[1024];
//        int length = 0;
//        while ((length=br.read(chars))!=-1){
//            String s = new String(chars, 0, length);
//            System.out.print(s);
//        }

        //一次读取一行数据
//        System.out.println(br.readLine());
//        System.out.println(br.readLine());
//        System.out.println(br.readLine());
//        System.out.println(br.readLine());
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }

        //释放资源
        br.close();
    }
}

2、字符输出流

普通字符输出流

字符输出流:
    Writer【抽象类】
        - OutputStreamWriter【具体实现子类】

OutputStreamWriter:
    构造方法:
        OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
        OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。
    成员方法:
        public void write(int c)
        public void write(char[] cbuf)
        public void write(char[] cbuf,int off,int len)
        public void write(String str)
        public void write(String str,int off,int len)

代码案例:


```plaintext
public class OutputStreamWriterDemo1 {
    public static void main(String[] args) throws Exception{
//        String s1 = "今天下午放假,不上课!";
////        byte[] bytes = s1.getBytes();
//        byte[] bytes = s1.getBytes("GBK");
//        System.out.println(Arrays.toString(bytes));
//
//        String s = new String(bytes,"GBK");
//        System.out.println(s);

        // 创建OutputStreamWriter(OutputStream out)对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java/src/com/shujia/day16/a3.txt"),"GBK");

        // public void write(int c) 一次写一个字符
//        osw.write(97);
//        osw.flush();

        //public void write(char[] cbuf) 一次写一个字符数组
//        char[] chars = {'我','爱','数','加'};
//        osw.write(chars);

        //public void write(char[] cbuf,int off,int len) 一次写字符数组的一部分
//        osw.write(chars,1,3);
//        osw.flush();

        //public void write(String str) 直接写一个字符串
//        osw.write("李刚是32期最帅的男人!");
//        osw.flush();

        //public void write(String str,int off,int len) 写字符串的一部分
//        osw.write("李刚是32期最帅的男人!",6,2);

        osw.write("中国");
        osw.flush();


        //释放资源
        osw.close();

    }
}

用上面的OutStreamReader创建字符输入流对象,还要传入一个字节输出流对象,挺麻烦的,java还有一个类描述字符输出流,FileWriter,使用该类创建字符输出流对象只用传文件地址就行了
FileWriter:
代码案例:

public class FileWriterDemo1 {
    public static void main(String[] args) throws Exception{
        //创建字符输出流对象
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java/src/com/shujia/day16/b3.txt"));
//        FileWriter fw = new FileWriter("java/src/com/shujia/day16/b2.txt");

        //创建字符输入流对象
//        InputStreamReader isr = new InputStreamReader(new FileInputStream("java/src/com/shujia/day16/b2.txt"));
        FileReader fr = new FileReader("java/src/com/shujia/day16/b2.txt");

        //一次读一个字符
//        int i = 0;
//        while ((i = fr.read())!=-1){
//            System.out.print((char) i);
//        }

        //一次读一个字符数组
        char[] chars = new char[1024];
        int length = 0;
        while ((length = fr.read(chars))!=-1){
            String s = new String(chars, 0, length);
            System.out.print(s);
        }


//        fw.write("今天的天气不错!");
//        fw.flush();

        fr.close();
//        fw.close();
    }
}

字符缓冲输出流

字符输出流:
    Writer【抽象类】
        - OutputStreamWriter【具体实现子类】
            - FileWriter【继承自OutputStreamWriter】
        - BufferedWriter【字符缓冲输出流】

  BufferedWriter【字符缓冲输出流】:
        构造方法:
            BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
        特殊方法:
            newLine(); // 默认会自动根据当前的系统生成一个换行符

代码案例:

public class BufferedWriterDemo1 {
    public static void main(String[] args) throws Exception{
        //BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
//        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("java/src/com/shujia/day16/b3.txt")));
        BufferedWriter bw = new BufferedWriter(new FileWriter("java/src/com/shujia/day16/b3.txt"));

        bw.write("落霞与孤鹜齐飞");
//        bw.write("\r\n"); // 这里的换行符需要根据将来运行的系统环境来设置
        bw.newLine(); // 默认会自动根据当前的系统生成一个换行符
        bw.write("秋水共长天一色");

        bw.flush();


        //释放资源
        bw.close();
    }
}

二、序列化

序列化:将对象转化成数据流一样在网络中传输
    对象输出流:ObjectOutputStream
    只有实现了Serializable接口的类的对象才可以进行序列化

反序列化:将网络中数据流还原成一个对象
    对象输入流:ObjectInputStream

 我们正常写一个对象之后,读取一个对象都是没有问题的。
 但是当我们修改了原来的类的时候,再次读取存储的对象就报错了
 java.io.InvalidClassException:
 com.shujia.day16.Teacher;
  local class incompatible:
    stream class desc serialVersionUID = -4530247781226673719,
    local class serialVersionUID = -4180828856871739850

 若不想让某一个成员序列化的话,只需要在该成员前面加上transient关键字

代码案例:

public class ObjectOutputStreamDemo1 {
    public static void main(String[] args) throws Exception{
//        write();

        read();
    }
    public static void read() throws Exception{
        //ObjectInputStream(InputStream in)
        //创建从指定的InputStream读取的ObjectInputStream
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("java/src/com/shujia/day16/obj.txt"));
        Object o = ois.readObject(); //Object o = new Teacher("小虎", 18)
        Teacher t1 = (Teacher)o;
        System.out.println(t1);


        ois.close();
    }

    public static void write() throws Exception{
        Teacher t1 = new Teacher("小虎", 18);
        //创建ObjectOutputStream对象
        //ObjectOutputStream(OutputStream out)
        //创建一个写入指定的OutputStream的ObjectOutputStream。
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("java/src/com/shujia/day16/obj.txt"));
        oos.writeObject(t1);
        oos.flush();

        //释放资源
        oos.close();
    }
}

三、总结

当一个文件打开能看懂,用字符缓冲流,看不懂用字节缓冲流

posted @ 2024-10-18 21:53  w我自横刀向天笑  阅读(1)  评论(0编辑  收藏  举报