• Java应用开发中的字符集与字符编码


    事出有因

    在向HttpURLConnection的输出流写入内容时,因没有设置charset,导致接收方对数据的验签不一致。

    URL url = new URL(requestUrl);
    //打开连接
    HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
    
    ......
    ......
    
    //获取输出流
    out = new OutputStreamWriter(urlConn.getOutputStream());
    //发送请求参数
    out.write(concatKeyValue(params, false));
    out.flush()

    回过头来看,问题看似挺容易解决,只需在获取输出流时,指定字符编码集

    out = new OutputStreamWriter(urlConn.getOutputStream(), "utf-8");

    但实则费了一番工夫。期间心里产生了过以下的问题:

    1、String.getBytes(String charset)与String(Byte[] bytes, String charset)的使用。

    2、什么场合下会涉及的字符编码的转换呢?

    3、在不显示指定charset时,java使用Charset.defaultCharset()来获取默认字符编码。Charset.defaultCharset()的值来自哪里?

    为了在以后的开发中,快速解决字符集相关问题。在这里对字符集做了一次比较系统的学习。

    字符集与字符编码

    字符是各种文字与符号的总称,比如语言符号、图形符号、标点。

    字符集是字符的集合,每个字符集包含的字符个数不同,常见的字符集有:unicode字符集、ISO 8859字符集、GB2312字符集、GB18030字符集、BIG5字符集等。

    字符编码是以二进制数字来对应字符集中的字符,使得计算机能够识别字符集中的字符。

    各个国家在制定编码标准的时候,通常是同时制定字符集与编码规范。因此常见的字符集,如GB2312,除了表示“字符集”这一层含义外,也包含了编码的含义。

    Unicode字符集有多种编码方式,如UTF-8、UTF-16等;ASCII只有一种;大多数MBCS(Multi-Byte Chactacter System,即多字节字符系统)(包括GB2312)也只有一种。

    Java

    Java中的字节码文件始终以unicode编码方式保存。Java运行时创建的字符串变量、常量等字符串均以unicode编码存储在内存中。

    当涉及数据读写时,就会涉及字符的编码转换问题,例如从磁盘读取文件时、向磁盘写入文件时、接收网络发送来的数据时等。

    数据存储到物理介质或通过物理介质传输时,都是以bit流的形态存在。而要传输正确的bit流,就需要声明和设置恰当的字符编码。

    getBytes()与getBytes(charset)

    当不指定字符集时,getBytes内部会获取当前操作系统的默认字符集。

    getBytes获得字符串的指定编码规范对应的字节数组,此过程称为编码。

    //s的字符编码方式为unicode(utf-16), jvm的默认编码规则
    String s = "我们";
    //得到s的gbk编码, unicode(utf-16) --> gbk
    byte[] bytes = s.getBytes("gbk");

    String的构造函数String(byte[] bytes, String charset)

    //解码,gbk --> unicode(utf-16)
    String p = new String(bytes, "gbk");

    Charset.defaultCharset()

    此方式用来获取默认字符集,默认字符集在jvm启动时已经根据系统环境确认,不可以修改(或者说修改并不会生效)。当jvm的启动时,也可以通过参数-Dfile.encoding指定字符集,或通过环境变量修改默认字符集。

    另外也请注意我们运行main方法与web项目的不同,它们启动了jvm的不同实例,所以默认字符集可能不同。所以如果在main方法中打印Charset.defaultCharset().name()的值 与实际运行web项目时输入的值不同,也不要觉得奇怪。

    但凡涉及中文(web开发、I/O、数据库读写等),乱码问题会与我们不期而遇,所以理解字符集和字符编码就很有必要。

    另外:

    当我们使用IDE(idea/eclipse)时,我们可以设置开发环境所使用字符集。请注意:IDE中设置的字符集只能代表IDE在存取源代码文件时使用了何种字符集,而不是class文件使用了何种字符集。

    好文推荐:《java中文乱码解决之道(五)—–java是如何编码解码的》

  • 相关阅读:
    redis五类型及原理|redis主从及问题|Uninstall Redis CentOs 7
    netty4与netty5序列化问题记录
    [转载]【深入Java虚拟机】之四:类加载机制
    序列化原理机制新谈
    [Eclipse使用技巧] Eclipse使用External Tools定位java 源文件目录路径
    学习vue的一些资源
    中国国内可用API合集
    适合初学者学习的的vue+webpack的小项目
    前端性能优化----yahoo前端性能团队总结的35条黄金定律
    Angular2优质学习资源收集
  • 原文地址:https://www.cnblogs.com/zhaojz/p/8329124.html
Copyright © 2020-2023  润新知