zoukankan      html  css  js  c++  java
  • 字符编码与序列化

    字符编码

    概述

    • 在计算机世界中,它只能识别二进制数据,每一个二进制位(bit)有0和1两种状态。而为了方便应用计算机,让它可以处理各种信息,便将所有的信息最终都表示为一个二进制的字符串。而各个国家的信息的载体我们可以看作是文字,将各个国家的文字用一连串二进制数据来表示,并一一对应,形成一张表,这张表便是编码表。

    • 而编码,就是制定一种规则,将字符映射到唯一一种状态(二进制字符串)。例如在ASCII编码中,字符 A 对应的二进制字符串为:01000001

    • 常见的字符编码如下图:

    image-20201010203454184

    注意

    • Unicode可以理解为全世界通用的编码表,这张表包含了可能出现的所有字符,每个字符对应一个数字,这个数字称为码点(Code Point)。注意它只是一个符号集,只规定的字符所对应的码点,并没有指定如何存储,如何进行存储有不同的编码方案。

    • Unicode编码方案主要有两条主线:UCSUTFUTF主线由Unicode Consortium进行维护管理,UCS主线由ISO/IEC进行维护管理。

    • Unicode码点转化为UTF-8编码的规则如下:

      • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
      • 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。如下:
      Unicode符号范围 (十六进制) (十进制)      |    UTF-8编码方式(二进制)
      ----------------------------------------------------------------------------------
      0000 0000-0000 007F (0-127)           |    0xxxxxxx (兼容ASCII码)
      0000 0080-0000 07FF (128-2047)        |    110xxxxx 10xxxxxx
      0000 0800-0000 FFFF (2048-65535)      |    1110xxxx 10xxxxxx 10xxxxxx
      0001 0000-0010 FFFF (65536-1114111)   |    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
      

    序列化

    概述

    • 对象序列化机制是指把内存中的Java对象转换成与平台无关的二进制内容,本质上就是一个byte[]数组,进而将该二进制内容持久的保存在磁盘上或通过网络传输到远程;当其他程序获取到该二进制内容时,可以恢复为原来的Java对象。简单来说:

      • 序列化:将对象变为二进制内容,写入到IO流中;
      • 反序列化:从IO流获取到二进制内容,将其恢复为对象。
    • 意义:序列化机制允许将实现序列化的Java对象转换为字节序列(也就是byte[]数组),这些字节序列可以保存在文件上,或通过网络传输,之后可以恢复成原来的对象。该机制使对象可以脱离程序的运行而独立存在。

    • 注意:在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都必须是可序列化的;同理,所有需要保存到磁盘的java对象都必须是可序列化的。

    • 一个Java对象要能序列化,必须实现java.io.Serializable接口或者java.io.Externalizable接口之一。Serializable接口没有定义任何方法,是一个空接口。称为“标记接口”。一旦实现了此接口,该类的对象就是可序列化的。

      public interface Serializable {}
      

    实现

    • 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制,把一个Java对象变为byte[]数组,它可以把一个Java对象写入一个字节流。
    • 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制,它从一个字节流读取Java对象。

    注意

    实现java.io.Serializable接口的对象

    • 反序列化并不会调用构造方法。反序列的对象是由JVM自己生成的对象,不通过构造方法生成。

    • 序列化同一对象多次,并不会将此对象序列化多次得到多个对象。

      • 因为保存在磁盘或文件中的对象都有一个序列化编码号;程序尝试序列化一个对象时,先检查该对象是否被序列化过,如果没有序列化,则将该对象序列化,如果已经序列化过,会直接输出该对象的序列化编码号。
      • 由于记录的是对象的序列化编码号。则当序列化一个可变对象后,也就是说更改了对象内容比如对象的名字由张三改为李四,再次序列化,并不会再次将更改后的对象转换为字节序列,也就是说再次序列化该对象时,通过反序列化得到的对象并非是更改后的李四,而是张三。

      image-20201017154252946

    • statictransient修饰的成员变量在序列化时,会忽略掉该成员变量。

      • transient关键字不能修饰方法和类,只能修饰变量;被transient修饰的字段是默认值,该字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
      • 默认值取值 引用类型:null、基本类型:0、boolean类型:false。
      • 静态变量不能被序列化,反序列化后类中static型变的值为当前JVM中对应static变量的值,并不是反序列化得到的。

    实现java.io.Externalizable接口的对象

    • 必须实现接口中的两个方法writeExternalreadExternal实现自定义序列化;

    • 就算类的变量被transient关键字修饰,依然可以序列化,Externalizable接口在反序列化时通过反射创建对象,因此该对象需要无参的构造方法。

    总结

    • 在使用转换流InputStreamReaderOutputStreamWriter 时,会指定字符编码,不恰当的指定编码格式会造成乱码等问题,字符编码章节是对常见的编码方式进行的对比与整理。
    • 在使用对象流ObjectInputStreamOjbectOutputSteam,会把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。这就涉及到了对象序列化的相关知识点,序列化章节整理了序列化时常见问题与注意点。

    欢迎关注
    公众号三筒记简介:分享各种编程知识、excel相关技巧、读书笔记

  • 相关阅读:
    Insus Meta Utility
    The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
    Insus Binary Utility
    asp.net实现文件下载功能
    Column 'Column Name' does not belong to table Table
    程序已被编译为DLL,怎样去修改程序功能
    如何在Web网站实现搜索功能
    如何把数据流转换为二进制字符串
    Asp.net更新文件夹的文件
    如何显示中文月份
  • 原文地址:https://www.cnblogs.com/manongxiao/p/14305701.html
Copyright © 2011-2022 走看看