详解Java中String类型与默认字符编码

为什么写这个

至于为什么要写这个,主要是一句mmp一定要讲,绕了一上午,晕死
Java程序中的中文乱码问题一直是一个困扰程序员的难题,自己也不例外,早在做项目时就遇到过很多编码方式的坑,当时想填来着,但是嫌麻烦。这次终于忍不住了,一定要弄个明白

String类型的编码方式

从网上查的资料都说,Java默认的字符编码是Unicode,而String类型的编码方式是与JVM编码方式和本机操作系统默认字符集有关的。于是我做出了测试
在Java中可以这样显示查看本地编码方式(JVM还是OS呢?)

// Gets the system property indicated by the specified key.
System.out.println(System.getProperty(file.encoding));

看注释上说是获取系统字符集,但是我对这个系统的概念表示存疑,为什么呢,因为众所周知,我们中国人的电脑大部分默认的字符编码方式就是GBK,在CMD中输入chcp可以获得一个数值936,这就表示了是GBK的编码方式。

但是我自己运行出这句话的结果竟然是UTF-8,我是在IDEA中运行的,并且已经使用IDEA设置了项目的编码方式是UTF-8,出现这样的结果我只能是猜测其实上面这句话是获取JVM(跟随项目的编码方式)的编码方式

接下来我们来回归正题,String类型的默认编码方式是什么,有下面这几句语句:

/* 测试String类型默认的编码方式
*/

// 使用String的有参构造方法
String str = new String("hhhh ty智障%shfu摸淑芬十分uif内服NSF黑");
// 1.以GBK编码方式获取str的字节数组,再用String有参构造函数构造字符串
System.out.println(new String(str.getBytes("GBK")));
// 2.以UTF-8编码方式获取str的字节数组,再以默认编码构造字符串
System.out.println(new String(str.getBytes("UTF-8")));

下面来看一下运行结果:

// 1.
hhhh ty����%shfu�����ʮ��uif�ڷ�NSF��i����ظ���u��Ϊ��ؼu ��δ���δ��� hhhh ty智障%shfu摸淑芬十分uif内服NSF黑i飞鸟回复额u发为呢丶u 房未婚夫未婚夫
// 2.
hhhh ty智障%shfu摸淑芬十分uif内服NSF黑i飞鸟回复额u发为呢丶u 房未婚夫未婚夫

可以很明显的可以看出,这里String类型默认的字符编码方式就是与我们查看本地系统的编码方式相同。因此我们得出结论:String类型的默认编码方式是和本地编码方式相关

String.getBytes()方法

我们大多数情况下是不使用String类型的,而是使用byte数组来传输操作数据,一般会使用String.getBytes()方法来将字符串转换成字节数组。但是这样转换的时候,会不会牵涉到编码问题呢?仔细查看了String.getBytes()的源码,分为无参的和有参的两种:

// 1.无参的getBytes()方法
  public byte[] getBytes() {
    // 再继续深入encode()方法可以发现使用的是系统默认的字符编码
    return StringCoding.encode(value, 0, value.length);
  }

// 2.带参数的getBytes(String charsetName)方法
  public byte[] getBytes(String charsetName)
      throws UnsupportedEncodingException {
    if (charsetName == null) throw new NullPointerException();
    // 继续深入可以发现,会使用参数字符集编码方式来返回字节数组,如果参数字符集不存在,则使用本地系统默认的字符编码
    return StringCoding.encode(charsetName, value, 0, value.length);
  }

综上,在这里再强调一下,因为修改了项目的编码方式,导致了本地系统的编码方式也变成了UTF-8,所以上述的实验都是基于IDE修改了工程项目编码方式的基础上

ByteBuffer与byte数组的互相转换

在NIO中,一般都是使用ByteBuffer来当作字符缓冲,而有的时候我们只有byte[]数组,所以是需要它们之间进行相互转换的

// ByteBuffer ----> byte[]
byte[] bytes = ByteBuffer.array();

// byte[] ------> ByteBuffer
byte[] bytes = new byte[1024];
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);

So

综上所述,再在这里总结一下:

  1. 本地JVM的编码方式是和本机OS默认的字符编码方式相关的,但是JVM的编码方式可以被修改
  2. Java程序的默认字符集是Unicode,在程序中声明的String类型的编码方式是和JVM编码方式相关的
  3. String.getBytes()方法默认的编码方式是JVM编码方式;同时还可以接收一个字符集名称当作参数,优先使用参数的字符集
  4. 因为Java代码使用的Unicode字符集,允许各编码方式之间转换,但不保证bit损失,所以String类型可以得到不同编码方式的byte数组,只要按照编码解码的方式获取字符串类型显示即可
  5. 文件的流通道是根据文件的编码方式决定的,所以不同编码方式的文件读写时要注意编码解码
  6. ByteBuffer声明的buffer可以与byte数组之间进行转换,但要注意的是ByteBuffer的大小一定要足够大以承载下所有的byte数组

小总结

搞清楚了这些甚是豁然开朗,其实很多时候中文的乱码问题根源就是编码方式与解码方式不一致,或者是不同编码方式之间转换时造成了bit损失。所以我们还是要注意规范化编码与解码方式,毕竟有的转换操作是不可逆的。

以上所述是小编给大家介绍的Java中String类型与默认字符编码详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Java在web页面上的编码解码处理及中文URL乱码解决

    编码&解码  通过下图我们可以了解在javaWeb中有哪些地方有转码: 用户想服务器发送一个HTTP请求,需要编码的地方有url.cookie.parameter,经过编码后服务器接受HTTP请求,解析HTTP请求,然后对url.cookie.parameter进行解码.在服务器进行业务逻辑处理过程中可能需要读取数据库.本地文件或者网络中的其他文件等等,这些过程都需要进行编码解码.当处理完成后,服务器将数据进行编码后发送给客户端,浏览器经过解码后显示给用户.在这个整个过程中涉及的编码解码的地方较

  • 浅析JAVA中toString方法的作用

    因为它是Object里面已经有了的方法,而所有类都是继承Object,所以"所有对象都有这个方法". 它通常只是为了方便输出,比如System.out.println(xx),括号里面的"xx"如果不是String类型的话,就自动调用xx的toString()方法 总而言之,它只是sun公司开发java的时候为了方便所有类的字符串操作而特意加入的一个方法 回答补充:写这个方法的用途就是为了方便操作,所以在文件操作里面可用可不用例子1: 复制代码 代码如下: publ

  • Java servlet 使用 PrintWriter 时的编码与乱码的示例代码

    在前面的网页中的编码与乱码系列中,曾多次提到使用 servlet 方式构建的动态响应流,不过在那里都是直接使用字节流的方式,不过,更为常见的方式是使用字符流.而在前面,又谈到了 Java 字节流与字符流的话题. 有了前面的基础,现在来说下 Java servlet 中使用字符流,也即是 PrintWriter 时的编码与乱码问题. 回顾字节流的情形 先回顾一下,在之前的字节流响应中,我们使用 String.getBytes 方法,然后总是显式传入编码的参数,使它与 meta 中或者 header

  • Java实现base64图片编码数据转换为本地图片的方法

    本文实例讲述了Java实现base64图片编码数据转换为本地图片的方法.分享给大家供大家参考,具体如下: 项目中用到的把base64图片数据转为本地图片的函数 /** * 替换html中的base64图片数据为实际图片 * @param html * @param fileRoot 本地路径 * @param serRoot 服务器路径 * @return */ public static String replaceBase64Image(String html,String fileRoot

  • 浅谈Java中Unicode的编码和实现

    Unicode的编码和实现 大概来说,Unicode编码系统可分为编码方式和实现方式两个层次. 编码方式 字符是抽象的最小文本单位.它没有固定的形状(可能是一个字形),而且没有值."A"是一个字符,"€"也是一个字符.字符集是字符的集合.编码字符集是一个字符集,它为每一个字符分配一个唯一数字. Unicode 最初设计是作为一种固定宽度的 16 位字符编码.也就是每个字符占用2个字节.这样理论上一共最多可以表示216(即65536)个字符.上述16位统一码字符构成基

  • 详解Java如何获取文件编码格式

    1:简单判断是UTF-8或不是UTF-8,因为一般除了UTF-8之外就是GBK,所以就设置默认为GBK. 按照给定的字符集存储文件时,在文件的最开头的三个字节中就有可能存储着编码信息,所以,基本的原理就是只要读出文件前三个字节,判定这些字节的值,就可以得知其编码的格式.其实,如果项目运行的平台就是中文操作系统,如果这些文本文件在项目内产生,即开发人员可以控制文本的编码格式,只要判定两种常见的编码就可以了:GBK和UTF-8.由于中文Windows默认的编码是GBK,所以一般只要判定UTF-8编码

  • Java实现BASE64编码和解码的方法

    BASE64和其他相似的编码算法通常用于转换二进制数据为文本数据,其目的是为了简化存储或传输.更具体地说,BASE64算法主要用于转换二进制数据为ASCII字符串格式.Java语言提供了一个非常好的BASE64算法的实现,.本文将简要地讲述怎样使用BASE64以及它是怎样工作的. Base64的作用:主要不是加密,它主要的用途是把一些二进制数转成普通字符用于网络传输.由于一些二进制字符在传输协议中属于控制字符,不能直接传送需要转换一下就可以了. 第一种方式: 通过反射使用java 中不对外公开的

  • 详谈java编码互转(application/x-www-form-urlencoded)

    本质上来说,java.net.UrlEncoder适用于将 String 转换为 application/x-www-form-urlencoded MIME 格式的静态方法 时 ,使用 但!一般情况下,web应用中,当你的服务器,页面编码,请求时编码都已经修改为 utf-8后,依然乱码时,此时则应试着用下方所写到的方法 使用URLDecoder将所乱码的数据进行解码, 而在此处简单说一下乱码的场景和简单转换时的执行原理: 首先,form表单提示数据时,默认Content-type:为 appl

  • Java Base64位编码与String字符串的相互转换,Base64与Bitmap的相互转换实例代码

    首先是网上大神给的类 package com.duanlian.daimengmusic.utils; public final class Base64Util { private static final int BASELENGTH = 128; private static final int LOOKUPLENGTH = 64; private static final int TWENTYFOURBITGROUP = 24; private static final int EIGH

  • java转换字符串编码格式的方法

    java转换字符串编码格式 (解码错误,重新解码) 字符集概念:规定了某个文字对应的二进制数字存放方式(编码)和某串二进制数值代表了哪个文字(解码)的转换关系. 我们在计算机屏幕上看到的是实体化的文字,而在计算机存储介质中存放的实际是二进制的比特流. 乱码场景(纯属瞎掰): 1) 前台输入utf-8编码的一串汉字(string1). (页面编码为utf-8, 在内存中会将这串汉字以utf-8编码为对应的二进制流存储) 2) 这串汉字(string1)的二进制流在经过http协议传输到后台时,这段

随机推荐