栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ooday07 2022.02.07 API第七天:

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ooday07 2022.02.07 API第七天:

0、序列化

1、创建Person,先执行OOSDemo,再执行OISDemo
--------------(1)对象序列化
-------------(1)对象反序列化

2、转换流
--------------(1)使用转换输出流向文件中写入文本数据:
--------------(2)使用转换流测试读取文本数据:

3、PrintWriter(自动行刷新功能)
-----------(1)缓冲字符输出流:java.io.PrintWriter:
-----------(2)在流链接中使用PW:

0、序列化
1、什么是序列化与反序列化?
序列化是指将对象的状态信息转换为可以存储或传输形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区。
以后可以通过从存储区中读取或者反序列化对象的状态,重新创建该对象。

①序列化:指把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。
--------(利用ObjectOutputStream,把对象的信息,按照固定的格式转成一串字节值输出并持久保存到磁盘)
②反序列化:把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。
--------(利用ObjectInputStream,读取磁盘中之前序列化好的数据,重新恢复成对象)


2、为什么要做序列化?
①、在分布式系统中,此时需要把对象在网络上传输,就得把对象数据转换为二进制形式,需要共享的数据的 JavaBean 对象,都得做序列化。
②、服务器钝化:如果服务器发现某些对象好久没活动了,那么服务器就会把这些内存中的对象持久化在本地磁盘文件中(Java对象转换为二进制文件);如果服务器发现某些对象需要活动时,先去内存中寻找,找不到再去磁盘文件中反序列化我们的对象数据,恢复成 Java 对象。这样能节省服务器内存。

3、Java 怎么进行序列化?
①、需要做序列化的对象的类,必须实现序列化接口:Java.lang.Serializable 接口(这是一个标志接口,没有任何抽象方法),Java 中大多数类都实现了该接口,比如:String,Integer
②、底层会判断,如果当前对象是 Serializable 的实例,才允许做序列化,Java对象 instanceof Serializable 来判断。
③、在 Java 中使用对象流来完成序列化和反序列化:()
ObjectOutputStream:通过 writeObject()方法做序列化操作
ObjectInputStream:通过 readObject() 方法做反序列化操作

(1)对象流
ObjectInputStream ObjectOutputStream类分别是InputStream和OutputStream的子类.

对象输出流 使用writeObject(Object obj)方法,将一个对象obj写入到一个文件,
		 使用readObject()读取一个对象。

(2)构造方法:

ObjectInputStream (InputStream in)
ObjectOutputStream(OutputStream out)

当准备将一个对象写入文件的时候,首先用OutputStream的子类创建一个输出流:
OutputStream outStream = new FileOutputStream("file_name");
ObjectOutputStream objstream = new ObjectOutputStream(outStream);

当使用对象流写入或者读取对象的时候,必须保证该对象是序列化的,这样是为了保证对象能够正确的写入文件,
并能够把对象正确的读回程序。

(3)对象的序列化

将对象转换成二进制数据流的一种实现手段,通过将对象序列化,可以方便的实现对象的传输及保存。
注:
①在Java中提供了ObejctInputStream 和ObjectOutputStream这两个类用于序列化对象的操作。用于存储和读取对象的输入输出流类。
*②要想实现对象的序列化需要实现Serializable接口,但是Serializable接口中没有定义任何的方法,仅仅被用作一种标记,以被编译器作特殊处理。
**③另外,Java.awt包中的Componet类是实现Serializable接口的类,因此程序可以实现把组件写入输出流,然后用输入流读取该组件的克隆。
1、创建Person,先执行OOSDemo,再执行OISDemo

对象流-------java.io.ObjectOutputStream和ObjectInputSteam

对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。

(1)对象序列化:将一个java对象按照其结构转换为一组字节的过程

(2)对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)

对象序列化的流连接操作原理图:

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

public class Person implements Serializable {  //①实现Serializable接口,  可序列化接口,规则

    
    static final long serialVersionUID = 1L;//只要版本号没变,就能反序列化(可以进行还原)

    private String name;
    private int age;
    private String gender;//性别
    
    
    private transient String[] otherInfo;//其他信息
    //private int salary;//工资  此时直接执行OISDemo会报错,出现一串数字,版本号不一致


    //alt+insert 自动生成代码的快捷键 调用构造器constructor 构造方法里要有这些参数
    public Person(String name, int age, String gender, String[] otherInfo) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.otherInfo = otherInfo;
    }

    //alt+insert 自动生成代码的快捷键 选择Getter and Setter全选后回车调用构造方法:
    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) +

                '}';
    }
}





(1)对象序列化:
package Vdayio;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class OOSDemo {
    public static void main(String[] args) throws IOException {
        String name = "苍老师";
        int age = 18;
        String gender = "女";
        String[] otherInfo = {"是一名演员", "来自霓虹", "爱好书法", "广大男性同胞的启蒙老师"};
        Person p = new Person(name, age, gender, otherInfo);
        System.out.println(p);//输出p.toString()返回值 在Person.java中调用该构造方法


        //将该Person对象写入文件person.obj中:
        //①因此程序可以实现把组件写入输出流,
        FileOutputStream fos = new FileOutputStream("./person.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fos);//

        
        oos.writeObject(p);
        System.out.println("写出完毕");

        oos.close();
    }
}



(2)对象反序列化:
package Vdayio;
import java.io.*;

public class OISDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream("person.obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
		
		
        //抛出异常的操作:alt+enter(回车)。选项第一项add exception...
        Person p = (Person)ois.readObject();//①然后用输入流读取该组件的克隆。
        System.out.println(p);

        ois.close();
    }
}
2、转换流

//java IO将流按照读写单位划分为字节流和字符流
字节流:以stream结尾的
字符流:read和writer

//转换流是一对常用的字符流实现类:java.io.InputStreamReader和OutStreamWriter
作用:
①在流连接中衔接其他高级字符流与下面的字节流(这也是转换流名字的由来)。
②负责将字符与对应的字节按照指定的字符集自动转换方便读写操作。
意义:
实际开发中我们还有功能更好用的字符高级流.但是其他的字符高级流都有一个共通点:不能直接连接在字节流上.而实际操作设备的流都是低级流同时也都是字节流.因此不能直接在流连接中串联起来.转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上.在流连接中起到"转换器"的作用(负责字符与字节的实际转换)

(1)使用转换输出流向文件中写入文本数据:

(1)使用转换输出流向文件中写入文本数据:
package Vdayio;
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);
//        String line = "我可以接受你的所有,所有小脾气";
//        byte[] date = line.getBytes(StandardCharsets.UTF_8);
//        fos.write(date);
//        fos.write("我可以带你去吃很多,很多好东西。".getBytes(StandardCharsets.UTF_8));
//        System.out.println("写出完毕!");

        //字符输出流支持直接写出字符串的write方法  同上:
        osw.write("我可以接受你的所有,所有小脾气。");
        osw.write("我可以带你去吃很多,很多好东西。");
        System.out.println("写出完毕!");

        osw.close();
    }
}

(2)使用转换流测试读取文本数据:

package Vdayio;
import java.io.*;
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);
        //读取1个字符,返回的int值内容本质上都是一个char。但是若返回的int为-1则表示读取到了末尾
//        int d = isr.read();
//        System.out.println((char)d);

        //同上:注意print不换行
        int d;
        while((d = isr.read()) !=-1){
            System.out.print((char)d);
        }

        isr.close();
    }
}
3、PrintWriter(自动行刷新功能)

------------------java.io.PrintWriter是具有自动行刷新功能的缓冲字符输出流,内部总是连接BufferedWriter
实际开发中缓冲字符输出流我们都使用它。
特点:
1:可以按行读写字符串
2:可以自动行刷新
3:可以提高写出字符的效率(实际由内部连接的BufferedWriter完整)

(1)缓冲字符输出流:java.io.PrintWriter:

①java.io.BufferedWriter和BufferedReader
②缓冲字符流内部也有一个缓冲区,读写文本数据以块读写形式加快效率.并且缓冲流有一个特别的功能:可以按行读写文本数据.
③java.io.PrintWriter具有自动行刷新的缓冲字符输出流,实际开发中更常用.它内部总是会自动连接BufferedWriter作为块写加速使用.

(1):
package Vdayio;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class PWDemo {
    public static void main(String[] args) throws FileNotFoundException {
        
        //向文件pw.txt中写入文本数据:
        PrintWriter pw = new PrintWriter("./pw.txt");

//        File file = new File("./pw.txt");//这两句意思同上。
//        PrintWriter pw = new PrintWriter(file);

        pw.println("该配合你演出的我演视而不见");//输出完毕后按行写在pw.txt中
        pw.println("别逼一个最爱你的人即兴表演");

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

(2)在流链接中使用PW:

PrintWriter的自动行刷新功能:
如果实例化PW时第一个参数传入的是一个流,则此时可再传入一个boolean型的参数,此值为true时就打开了自动行刷新功能。
即:每当我们用PW的println方法写出一行字符串后会自动flush。

package Vdayio;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class PWDemo02 {
    public static void main(String[] args) throws IOException {
        //文件字节输出流(是一个低级流),向文件中写入字节数据
        FileOutputStream fos = new FileOutputStream("pw2.txt");
        //转换输出流(是一个高级流,且是一个字符流)。1:衔接字符与字节流 2:将写出的字符转换为字节
        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        //缓冲输出流(是一个高级流,且是一个字符流)。块写文本数据加速
        BufferedWriter bw = new BufferedWriter(osw);

        
        //具有自动行刷新的缓冲字符输出流:
        PrintWriter pw = new PrintWriter(bw,true);//true:[相当于pw.flush();自动行刷新功能]


        //:完成简易记事本。控制台输入的每行字符串都按行写入文件。单独输出exit时退出。
        Scanner scanner = new Scanner(System.in);
        while(true){
            String line = scanner.nextLine();
            if("exit".equalsIgnoreCase(line)){  //equals:区分大小写  equalsIgnoreCase:不区分大小写
                break;
            }
            pw.println(line);
//            pw.flush();//自动行刷新功能
        }
        pw.close();
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/732130.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号