【JavaSE】IO流2[常用IO流对象]

① 常用IO流对象

- 文件字节流

  • FileInputStream :
    通过字节的方式读取文件,适合读取所有类型的文件(图像, 视频, 文本等等), 当然Java也提供了FileReader来专门用来读取文本文件
import java.io.FileInputStream;

public class FileStreamDemo {
    public static void main(String[] args) {
        FileInputStream fis = null;

        try{
            //创建文件字节输入流
            fis = new FileInputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\img.png");   //节点流,直接和数据源挂钩
            int temp = 0;
            int i = 0;
            while((temp = fis.read()) != -1){   //返回的是0~255之间的一个整数
                System.out.print("\t" + temp);
                if(i % 20 == 0) System.out.println();
                i++;
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(fis == null){
                    fis.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

  • FileOutputStream :
    通过字节的方式写入数据到文件中,适合所有类型的文件, Java也提供FileWriter专门写入文本文件
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class FileStreamDemo {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try{
            //创建文件字节输入流
            fis = new FileInputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\img.png");   //节点流,直接和数据源挂钩

            //创建文件字节输出流对象
            fos = new FileOutputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\new.png");
            int temp = 0;
            while((temp = fis.read()) != -1){   //返回的是0~255之间的一个整数
                //System.out.print("\t" + temp);
                fos.write(temp);
            }
            fos.flush();   //将数据从内存中写到磁盘中(进行操作时,数据会暂存在内存里边9)
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(fis == null){   //字节输入流对象的关闭
                    fis.close();
                }

                if(fos != null){   //字节输出流对象的关闭
                    fos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

通过缓冲区提高读写效率

以上案例中, 进行读写都是一个字节一个字节进行的, 相对来说效率很低. 所以需要一个能够提高读写效率的方法.

方式一
  • 通过创建一个指定长度的数组作为缓冲区,以此来提高IO流的读写效率, 该方式适用于读取较大图片的缓冲区定义.
  • 注意: 缓冲区的长度一定是二的整数幂, 一般情况下1024长度比较合适.
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class FileStreamBuffered {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try{
            //创建文件字节输入对象
            fis = new FileInputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\img.png");
            //创建文件字节输出对象
            fos = new FileOutputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\new2.png");

            //创建一个字节缓冲区,提高读写效率
            byte[] buff = new byte[2048];
            int temp = 0;
            while((temp = fis.read(buff)/*将数据存到缓冲区里*/) != -1){   //read返回的是当前数组的长度
                //fos.write(buff);
                fos.write(buff,0,temp);
            }

            fos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(fis != null){
                    fis.close();
                }
                if(fos != null){
                    fos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

方式二

通过创建一个字节数组作为缓冲区, 数组的长度是通过流对象的available()返回当前文件的预估长度来定义的.在进行读写文件时, 是在一次读写操作中完成文件操作的.
注意: 如果文件过大, 那么对内存的占用也是较大的. 大文件不建议使用该方法.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileStreamBuffer2 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\img.png");
            fos = new FileOutputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\new3.png");

            byte[] buff = new byte[fis.available()];
            //一次性进行读取, 但是对内存的占用太大,大文件读写的时候不建议使用
            fis.read(buff);
            fos.write(buff);
            fos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try{
                if(fis != null){
                    fis.close();
                }
                if(fos != null){
                    fos.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

通过字节缓冲流提高读写效率

  • Java缓冲流的本身并不具有IO流的读取与写入的功能,只是在别的流(节点流或者其它处理流)上加上缓冲功能提高效率, 就像把别的流包装起来一样, 因此, 缓冲流是一种处理流.
    当对文件或者其它数据进行频繁的读写操作时,效率比较低, 这时, 如果使用缓冲流就能够读取到更多的信息. 因为缓冲流是先将数据缓存起来, 当缓存区存满后,或者手动刷新时再一次性的读取到程序或者写入目的地.
  • BufferedInputStream和BufferedOutputStream这两个流是缓冲字节流, 通过内部的缓存组来提高操作的效率.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class BufferedStream {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try{
            fis = new FileInputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\img.png");
            bis = new BufferedInputStream(fis);
            //可以直接只用匿名内部类的方法拿到缓冲流对象
//            BufferedInputStream buffIn = new BufferedInputStream(new FileInputStream("......"));
            
            fos = new FileOutputStream("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\new3.png");
            bos = new BufferedOutputStream(fos);
            //缓冲区流 byte数组长度默认为8192

            int temp = 0;
            while((temp = bis.read()) != -1){
                bos.write(temp);
            }

            bos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                //注意:关闭流对象的顺序-->后开的先关闭
                if(bis != null){
                    bis.close();
                }
                if(fis != null){
                    fis.close();
                }
                if (bos != null){
                    bos.close();
                }
                if(fos != null){
                    fos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

定义文件拷贝工具类

对于文件拷贝这一类的常用操作,可以直接定义一个工具类,来进行文件的拷贝,方便后期的调用

import java.io.*;

public class CopyFile {
    public static void main(String[] args) {
        copyFile("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\img.png",
                "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\bewCopy.png");
    }

    /**
     * 定义文教拷贝的工具类
     * @param src 拷贝文件的额原路径
     * @param des 拷贝文件的目标路径
     */
    public static void copyFile(String src,String des){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            //通过匿名内部类创建包装流对象
            bis = new BufferedInputStream(new FileInputStream(src));
            bos = new BufferedOutputStream(new FileOutputStream(des));

            //拷贝的核心代码
            int temp = 0;
            while((temp = bis.read()) != -1){
                bos.write(temp);//包装类内部维护这一个长度为8192的数组,以提高效率
            }

            bos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(bis != null){
                    bis.close();
                }
                if(bos != null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

- 文件字符流

不同于文件字节流, 文件字符流只能处理文本文件, 它可以对单个字符进行操作.

文件字符输入流

import java.io.FileReader;
import java.io.IOException;

public class FileReaderDemo {
    public static void main(String[] args) {
        FileReader frd = null;
        try {
            //创建文件字符输入流对象
            frd = new FileReader("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\Test.txt");

            int temp = 0;
            while((temp = frd.read()) != -1){
                System.out.print((char)temp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try{
                if(frd != null){
                    frd.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

文件字节输出流

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo {
    public static void main(String[] args) {
        FileWriter fw = null;
        FileWriter fw2 = null;
        try {
             fw = new FileWriter("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\writer.txt");
             //同一个对象操作同一个文件时,默认会进行追加写入
             fw.write("Although life is hard !\r\n");
             fw.write("iFinder will never abandon !\r\n");
             fw.flush();

             //不同的对象操作同一个文件时,在获取对象时传入参数,才会进行追加操作
             fw2 = new FileWriter("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\writer.txt",
                     true);
             fw2.write("生活会欺骗你\r但是学习不会");
             fw2.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(fw != null){
                    fw.close();
                }
                if(fw2 != null){
                    fw2.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }

    }
}

使用字符流实现文本文件的拷贝

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class StringFileCopy {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;

        try {
            fr = new FileReader("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongText.txt");
            fw = new FileWriter("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\TextCopy.txt");

            //创建一个缓冲区以提高读写的效率
            char[] buff = new char[2048];
            int temp = 0;
            while((temp = fr.read(buff)) != -1){
                fw.write(buff,0,temp);
            }

            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(fr != null){
                    fr.close();
                }
                if(fw != null){
                    fw.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

- 字符缓冲流

与字节缓冲流相仿, 字符缓冲流同样增加了缓存机制, 大大提高了文件的读写效率.

  • BufferedReader :
    针对字符输入的缓冲流对象, 提供了更方便的按行读取的方法 readLine();
    在使用字符缓冲流读取文本时, 可以更加方便的使用行为单位进行读取.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        BufferedReader br = null;

        try{
            br = new BufferedReader(new FileReader(
                    "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongText.txt"));
            String temp = null;
            int i = 1;
            while((temp = br.readLine()) != null){   //使用readLine读取时,null为结束标志
                System.out.println(i + "\t" + temp);
                i++;
            }


        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(br != null){
                    br.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

  • BufferedWriter :
    是针对字符输出流的缓冲流对象,在字符输出缓冲流中可以使用newLine(),方便实现换行的处理.
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo {
    public static void main(String[] args) {
        BufferedWriter bw = null;

        try {
            bw = new BufferedWriter(new FileWriter(
                    "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\B_writer.txt"));
            bw.write("学习使人进步");
            bw.newLine();   //换行
            bw.write("懈怠导致灭亡");
            bw.newLine();
            bw.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(bw != null){
                    bw.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

通过缓冲流实现对文件的拷贝

import java.io.*;

public class BufferStringCopy {

    public static void main(String[] args) {
        copyFile("C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongText.txt",
                "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\CopyLongText.txt");
    }

    /**
     * 基于字符缓冲流实现文件拷贝
     * @param src  源文件目录
     * @param des  目标文件目录
     */
    public static void copyFile(String src , String des){
        BufferedReader br = null;
        BufferedWriter bw = null;

        try {
            br = new BufferedReader(new FileReader(src));
            bw = new BufferedWriter(new FileWriter(des));
            
            String temp = "";
            while((temp = br.readLine()) != null){
                bw.write(temp);
                bw.newLine();   //一行一样读取,一行一行输出
            }
            bw.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(br != null){
                    br.close();
                }
                if(bw != null){
                    bw.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

通过字符缓冲流为文件内容添加行号

import java.io.*;

public class LineNumDemo {
    public static void main(String[] args) {
        BufferedReader br = null;
        BufferedWriter bw = null;

        try{
            //通过匿名内部类,实现缓冲流的获取
            br = new BufferedReader(new FileReader(""));
            bw = new BufferedWriter(new FileWriter(""));

            int i = 1;
            String temp = "";   //readLine()的返回值是一个String类型的数据
            while((temp = br.readLine()) != null){   //readLine方法判断读取结束的标识为null
                bw.write(i + temp);
                bw.newLine();   //按行获取的输入数据,输出是需要进行换行处理
                i++;
            }
            bw.flush();

        }catch (IOException e){
            e.printStackTrace();
        }finally{
            try{   //关闭流的操作
                if(br != null){
                    br.close();
                }
                if(bw != null){
                    bw.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

- 转换流

通过转换流实现键盘输入屏幕输出

  • Java中 InputStreamReader/OutputStreamWriter用来实现字节流转化成字符流. 字节流→字符流
  • System.in是字节流对象, 代表键盘的输入, 如果我们想按行来接受用户的输入时, 就必须用到字符缓冲流BufferedReader特有的readLine()方法, 但是获取BufferedReader实例的时候, 需要传入一个reader对象作为参数, 这时候就需要用到InputStreamReader转换流了.
  • 而System.out也是字节流对象,代表输出显示器, 按行获取用户输入以后, 需要将读取的一行直接输出到显示器, 就需要字符流的write(String str)方法, 所以要使用OutputStreamWriter将字节流转化为字符流.
import java.io.*;

public class ConvertStream {
    public static void main(String[] args) {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try{/*
            InputStream in = System.in;   //基于字节的方式,获取用户输入的内容
            int input = in.read();
            System.out.println(input);   //返回的是单独的字符int值
            */
            //通过转换流获取键盘的字节输入数据,再将数据包装成Reader对象
            br = new BufferedReader(new InputStreamReader(System.in));
            String input = br.readLine();   //直接获取一行的输入数据
            System.out.println(input);
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
            bw.write(input);
            bw.flush();

            //实现反复输入
            while(true){
                bw.write("请输入: ");
                bw.flush();
                String str = br.readLine();
                if(str.equals("exit")) {
                    break;
                }
                bw.newLine();
                bw.write("输入的是: " + str);
                bw.newLine();

            }

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(br != null){
                    br.close();
                }
                if(bw != null){
                    bw.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }

    }
}

利用字节流实现添加文本的行号

import java.io.*;

public class LineNumDemo2 {
    public static void main(String[] args) {
        BufferedReader br = null;
        BufferedWriter bw = null;

        try{
            br = new BufferedReader(   //缓冲流对象,实现文本文件的行号添加,按行输出
                    new InputStreamReader(   //转换流对象,将字节流包装成字符流
                            new FileInputStream(   //文件字节输入对象
                                    "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongText.txt")));
            bw = new BufferedWriter(   //缓冲流
                    new OutputStreamWriter(   //转换流
                            new FileOutputStream(   //字节流
                                    "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongTextBW.txt")));
            String temp = "";
            int i = 1;
            while((temp = br.readLine()) != null){
                bw.write(i + "\t " + temp);   //写入一行
                bw.newLine();   //换行
                bw.flush();
                i++;
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(br != null){
                    br.close();
                }
                if(bw != null){
                    bw.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

- 字符输出流

  • 在Java的IO流中专门提供了用于字符输出的流对象PrintWriter。该对象具有自动行刷新缓冲字符输出流,特点是可以按行写出字符串,并且可以通过println()方法实现自动换行。
import java.io.*;

public class PrintWriterDemo {
    public static void main(String[] args) {
        BufferedReader br = null;
        PrintWriter pw = null;
        try{
            br = new BufferedReader(   //缓冲流
                    new InputStreamReader(   //字节→字符转换流
                            new FileInputStream(   //字节节点流
                                    "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongText.txt")));
            pw = new PrintWriter(   //这是一个节点流,直接和文件打交道
                    "C:\\Users\\iFinder\\Desktop\\Java Learnning\\JavaSE\\src\\com\\IOLearning\\LongTextPW.txt");
            String temp = "";
            int i = 1;
            while((temp = br.readLine()) != null){
                pw.println("//" + temp + "\t" + i);   //自带刷新流的能力,能够自动换行
                i++;
            }

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(br != null){
                    br.close();
                }
                if(pw != null){
                    pw.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

- 字节数组流

  • ByteArrayInputStream和ByteArrayOutputStream经常用在流和数组之间需要转换的情况下。

字节数组输入流

事实上,FileInputStream是把文件当作数据源。而ByteArrayInputStream则是把内存中的字节数组对象当作数据源。

import java.io.ByteArrayInputStream;

public class ByteArrayInputStreamDemo {
    public static void main(String[] args) {
        byte[] arr = "iFinderWillGetAJob".getBytes();
        ByteArrayInputStream bis = null;
        StringBuilder sb = new StringBuilder();

        try{
            //该构造方法的参数是一个字节数组,这个字节数组就是数据源
            bis = new ByteArrayInputStream(arr);
            int temp = 0;
            while((temp = bis.read()) != -1){
                sb.append((char)temp);
            }
            System.out.println(sb.toString());
        }finally {
            try{
                if(bis != null){
                    bis.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

字节数组输出流

ByteArrayOutputStream流对象,是将流中的数据写入到字节数组中。

import java.io.ByteArrayOutputStream;
import java.util.Arrays;

public class ByteArrayOutputDemo {
    public static void main(String[] args) {
        ByteArrayOutputStream bos = null;

        try{
            bos = new ByteArrayOutputStream();   //不需要任何参数
            bos.write('a');   //直接写字符是可以的
            bos.write('b');

            byte[] arr1 = bos.toByteArray();
            System.out.println(Arrays.toString(arr1));   //[97, 98]
        }finally {
            try{
                if(bos != null){
                    bos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

- 数据流

  • 数据流将“基本数据类型”和“字符串类型”作为数据源,从而允许程序以与机器无关的方式,从底层输出流中操作Java的基本数据类型与字符串类型。将读取到的基本类型数据直接输出,不需要在程序中进行转换
  • DataInputStream和DataOutputStream提供了可以存取与机器无关的所有Java基础类型的数据(int double String等)的方法。

数据输出流

import java.io.*;

public class DataOutputDemo {
    public static void main(String[] args) {
        DataOutputStream dos = null;
        try {
            dos = new DataOutputStream(   //数据流
                    new BufferedOutputStream(   //缓冲流
                            new FileOutputStream("E:/data.txt")));   //节点流

            dos.writeInt(123);
            dos.writeBoolean(true);
            dos.writeDouble(Math.random());
            dos.writeChar('s');
            dos.writeUTF("你好iFinder");
            dos.flush();   //写出数据后,因为是字节类型的数据,所以打开后会显示乱码
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(dos != null){
                    dos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

数据输入流

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class DataInputDemo {
    public static void main(String[] args) {
        DataInputStream dis = null;
        try{
            dis = new DataInputStream(   //数据输入流
                    new BufferedInputStream(   //字节缓冲流
                            new FileInputStream("E:/data.txt")));   //字节节点流
            //直接读取数据,注意,读取的顺序要与写入的顺序一致,否则,无法正确的读取
/*          dos.writeInt(123);
            dos.writeBoolean(true);
            dos.writeDouble(Math.random());
            dos.writeChar('s');
            dos.writeUTF("你好iFinder");
            dos.flush();
*/
            System.out.println("Int:" + dis.readInt());
            System.out.println("boolean:" + dis.readBoolean());
            System.out.println("Double:" + dis.readDouble());
            System.out.println("Char:" + dis.readChar());
            System.out.println("String:" + dis.readUTF());

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(dis != null){
                    dis.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

- 对象流

  • 对象的本质是用来组织与存储数据的,且对象本身也是数据。如果需要将对象存储到硬盘中,或通过网络传输到另一台PC,则我们可以通过序列化与反序列化实现这样的需求。

对象的序列化与反序列化

  • 把Java对象转换为字节序列的过程叫做,对象的序列化
    把字节序列恢复为Java对象的过程叫做,对象的反序列化

  • 当Java对象需要在网络上进行传输时,发送方需要将对象序列化为二进制文件在网络上进行传送。而接收方则需要对收到的二进制序列文件进行反序列化,将数据恢复为Java对象才能正常的运行。

  • 对象序列化的作用:
    持久化:把对象的序列永久的保存到硬盘上,通常存放在文件夹当中。
    网络通信:在网络上传输对象的字节序列。例如:服务器之间的通信、对象的传递。

序列化涉及的类和接口

  • ObjectOutputStream–对象输出流,它的writeObject(Object obj)方法可以对指定的obj对象进行序列化进而写到一个目标输出流当中
  • ObjectInputStream–对象输出流,它的readObject()方法会从一个源输入流中读取字节序列进而反序列化为一个对象,并将其返回
  • 注意:只有实现了Serializable接口的对象才能够被序列化。而Serializable接口是一个空接口,只起到标记的作用。

对象流操作基本数据类型

  • 上文提到的数据流只能实现对基本数据类型和字符串类型的读写,并不能对Java对象进行读写操作(字符串除外),但是在对象流中,不仅实现了对基本类型的操作,并且还可以对Java对象进行处理。
写出基本类型数据
import java.io.*;

public class ObjectOutputBasicType implements Serializable {
    public static void main(String[] args) {
        ObjectOutputStream oos = null;

        try{
            oos = new ObjectOutputStream(   //对象流
                    new BufferedOutputStream(   //缓冲流
                            new FileOutputStream("E:/Objet.txt")));   //节点流
            oos.writeInt(90);
            oos.writeChar('r');
            oos.writeUTF("iFinder");
            oos.flush();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(oos != null){
                    oos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
读取基本类型数据
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ObjectInputBasicType {
    public static void main(String[] args) {
        ObjectInputStream ois = null;

        try{
            ois = new ObjectInputStream(
                    new BufferedInputStream(
                            new FileInputStream("E:/Object.txt")));
            //与数据流相同,必须按写入的顺序读取数据
/*
            oos.writeInt(90);
            oos.writeChar('r');
            oos.writeUTF("iFinder");
            oos.writeObject(new ObjectOutputBasicType());
*/
            System.out.println("Int: " + ois.readInt());
            System.out.println("Char: " + ois.readChar());
            System.out.println("String: " + ois.readUTF());
            System.out.println("Object: " + ois.readObject().toString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(ois != null){
                    ois.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

对象流操作对象

  • ObjectOutputStream可以将一个内存中的Java对象通过序列化的方式写入到磁盘文件中。被序列化的对象必须实现Serializable接口,否则会抛出异常。
创建对象
import java.io.Serializable;

public class Users implements Serializable {
    private int userid;
    private String username;
    private int userage;

    public Users(int userid, String username, int userage) {
        this.userid = userid;
        this.username = username;
        this.userage = userage;
    }

    @Override
    public String toString() {
        return "id: " + userid + 
                "name: " + username + 
                "age: " + userage;
    }
}

将对象序列化到磁盘
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class ObjectOutputObjType {
    public static void main(String[] args) {
        ObjectOutputStream oos = null;

        try{
            oos = new ObjectOutputStream(
                    new FileOutputStream("E:/ObjOut.txt"));   //输出流一定是一个字节输出流
            Users users = new Users(123,"iFinder",23);
            //进行序列化
            oos.writeObject(users);
            oos.flush();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(oos != null){
                    oos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
将对象反序列化到内存
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ObjectInputObjType {
    public static void main(String[] args) {
        ObjectInputStream ois = null;

        try{
            ois = new ObjectInputStream(
                    new FileInputStream("E:/ObjOut.txt"));

            Users users = (Users) ois.readObject();   //强制类型转换,获取对象
            System.out.println(users.toString());
            /*
                id: 123
                name: iFinder
                age: 23
             */
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(ois != null){
                    ois.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值