美文网首页
深入分析java Web技术内幕 - 编码(3)

深入分析java Web技术内幕 - 编码(3)

作者: attentionYSF | 来源:发表于2019-08-26 22:55 被阅读0次
为什么要编码?

计算机存储信息的最小单位是1byte,即8bit,所能表示的字符个数为255个,但是人类要表示的符号太多,远远不止255个,西欧字符、中文等等符号。

解决这个问题,就必须要有一个新的数据结构,在java中就是char,从char到byte必须编码(可以理解为翻译)

常见编码格式(字典)
  1. ASCⅡ
    由于计算机最早是由美国发明的,根据他们的语言习惯,用1个字节可以表示128个字符,可以通过键盘输入并且能够显示出来
  2. ISO-8859-1
    应用最广泛的编码格式,占用2个字节可以表示256个字符,涵盖大部分的西欧语言字符。
  3. 中文编码
    • GB2312
      包含682个字符和6763个汉字
    • GBK
      总共有23940个码位,能表示21003个汉字,兼容GB2312
    • GB18030
      国家标准,兼容GB2312,但是应用不广泛
  4. Unicode
    统一编码,是计算机科学领域里的一项业界标准,包括字符集、编码方案。
  5. UTF-16
    用两个字节,将Unicode字符转换为字节存储。Java以UTF-16作为内存的字符存储格式
  6. UTF-8
    变长,1-6个字节
Java中的编码场景

磁盘I/O 和 网络I/O

磁盘I/O
  • 字符转字节:OutputStreamWriter作为桥梁,传入字符集charset,委托StreamDecoder去做具体的字符转字节的工作
  • 字节转字符:InputStreamReader 作为桥梁,传入字符集charset,委托StreamDecoder去做具体的字节转字符的工作
 //字符转字节
    @Test
    public void charToByteByDiskIo() {
        String path = CodeProgram.class.getResource("").getPath();
        File file = new File(path, "字符转字节流,通过字符写入磁盘文件.txt");
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        try {
            fos = new FileOutputStream(file);
            osw = new OutputStreamWriter(fos, "utf-8");
            osw.write("我爱中国,我爱香港!");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null != osw) {
                    osw.close();
                }
                if(null != fos) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
//字节转字符:打印当前java类的内容到控制台(如果eclipse中的workspace文件编码未改为utf-8或者测试方法所属的java类的文件编码没有改为utf-8,则会乱码)
@Test
    public void byteToCharByDiskIo() {
        File directory = new File("./src");
        File file = new File(directory, "CodeProgram.java");
        FileInputStream fis = null;
        InputStreamReader isr = null;
        try {
            fis = new FileInputStream(file);
            isr = new InputStreamReader(fis, "utf-8");
            StringBuffer sb = new StringBuffer();
            char[] cbuf = new char[1024];
            int length = 0;
            while((length = isr.read(cbuf)) != -1) {
                sb.append(cbuf, 0, length);
            }
            System.out.println(sb.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null != isr) {
                    isr.close();
                }
                if(null != fis) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
网络I/O
  1. URL的编解码
  2. HTTP Header的编解码
  3. POST表单的编解码
  4. HTTP Body的编解码
  5. 外部引入JS文件
  6. JS的URL编码及服务端解码
  7. 其他需要编码的地方
    以Tomcat服务器为例讲解
  1. URL的编解码
    Get请求,URL的pathinfo(路径)和Query String(参数)的编码字符集不同,浏览器将URL中非ASCⅡ码字符按某种字符集转换为16进制到字符加上%。
    tomcat设置URI解码字符集为UTF-8:<Connector URIEncoding="UTF-8" />
    tomcat设置Query String解码字符集为UTF-8:<Connector URIEncoding="UTF-8" useBodyEncodingForURI="true" />
  2. HTTP Header的编解码

    默认为ISO-8859-1,且不提供编码设置到方法,只能用URLEncoder编码,服务端request.getHeader时,再相应到用URLEncoder解码

  3. POST表单的编解码

    手动指定编码格式, request.setCharacterEncoding(charset),post表单提交到数据就是以指定到编码格式编码,再调用request.getParameter(),会自动用设定到编码去解码。
    一定要在调用request.getParameter()方法前调用request.setCharacterEncoding(charset),否则tomcat在解析前会检测HTTP Header中到contentType,一般请求时,这个值是null,根据tomcat源码,为空时,按默认到到字符集ISO-8859-1来编码,导致乱码

  4. HTTP Body的编解码

    请求资源成功获取后,这些内容将通过response返回给客户端浏览器。通过response.setCharacterEncoding(charset)设置编解码字符集,通过response Header的contentType返回给客户端,浏览器根据contentType解码,如果不存在,则根据html <meta/>中到charset来解码,如果都不存在,则用默认到ISO-8859-1解码

  5. 外部引入JS文件

    如果在一个单独到js脚本中包含中文输出,需指定字符集<script src="" charset="gbk" />
    如果被一个页面引入到js脚本,则与外部页面到编码方式一致,若js文件本身到编码格式与外部页面编码格式不一致,则会乱码

  6. JS的URL编码及服务端解码
    • encodeURI()
    • encodeURIComponent()

    除了特殊字符加英文字母不编码加%外,其余到都编码;后者到特殊字符范围缩小,特别是&符号不包含在内,&符号也要编码。所以后者常用来对一个URL传递一个参数值为URL的URL进行编码。后台对应到解码JAVA类为URLDecoder。前端JS两次编码,后端request.getParameter()自动解一次码,URLDecoder.decoder手动解一次码。两次编解码避免了前后端第一次编解码不一致的问题。

  7. 其他需要编码的地方
    • 数据库连接JDBC URL传递characterEncoding=gbk,与数据库内置编码格式要一直
    • XML
    • JSP

相关文章

  • Java Web

    ref: 深入分析Java Web技术内幕 总结:Spring事务配置 Ch 1 深入Web请求过程 CDNCon...

  • 深入分析java Web技术内幕 - 编码(3)

    为什么要编码? 计算机存储信息的最小单位是1byte,即8bit,所能表示的字符个数为255个,但是人类要表示的符...

  • java class文件结构

    (<深入分析Java Web技术内幕>笔记)java语言在宣传时打出的名号就是"一次编译,到处运行", 也就是支持...

  • javac编译原理

    第二章 Javac编译原理 注:本文主要记录自《深入分析java web技术内幕》"第四章 javac编译原理" ...

  • 深入分析java web技术内幕

    此书时候闲暇时间阅读,或者寻求技术难题解决方案的时候阅读。 但是直接I/O有负面影响,如果访问的数据不在应用程序缓...

  • GET请求中中文乱码的解决

    GET请求中的乱码原理解析和解决方案 《深入分析javaweb技术内幕》第三章 web应用中浏览器与服务端的编码和...

  • 深入分析Java web 技术内幕4——中文编码问题

    原因:符号太多,一个字节无法表示,需要数据结构char类型 面临着在存储空间和编码效率之间选择 由IO 的地方就有...

  • JavaWeb笔记之——Web请求过程

    本文总结自《深入分析Java Web技术内幕》一书。全篇内容大致先从一个面试经常问及的问题说起,然后再介绍各个主要...

  • 深入分析JAVA_WEB技术内幕

    第一章 深入WEB请求过程 1.1 B/S网络架构概述 1.2 如何发起一个请求 1.3 HTTP解析 常见的HT...

  • 深入分析JAVA WEB技术内幕(二)

    JAVA NIO概述 NIO的工作机制 channel和selector的概念在NIO中尤为突出。channel可...

网友评论

      本文标题:深入分析java Web技术内幕 - 编码(3)

      本文链接:https://www.haomeiwen.com/subject/anddectx.html