详解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
综上所述,再在这里总结一下:
- 本地jvm的编码方式是和本机os默认的字符编码方式相关的,但是jvm的编码方式可以被修改
- java程序的默认字符集是unicode,在程序中声明的string类型的编码方式是和jvm编码方式相关的
- string.getbytes()方法默认的编码方式是jvm编码方式;同时还可以接收一个字符集名称当作参数,优先使用参数的字符集
- 因为java代码使用的unicode字符集,允许各编码方式之间转换,但不保证bit损失,所以string类型可以得到不同编码方式的byte数组,只要按照编码解码的方式获取字符串类型显示即可
- 文件的流通道是根据文件的编码方式决定的,所以不同编码方式的文件读写时要注意编码解码
- bytebuffer声明的buffer可以与byte数组之间进行转换,但要注意的是bytebuffer的大小一定要足够大以承载下所有的byte数组
小总结
搞清楚了这些甚是豁然开朗,其实很多时候中文的乱码问题根源就是编码方式与解码方式不一致,或者是不同编码方式之间转换时造成了bit损失。所以我们还是要注意规范化编码与解码方式,毕竟有的转换操作是不可逆的。
以上所述是小编给大家介绍的java中string类型与默认字符编码详解整合,希望对大家有所帮助
推荐阅读
-
详解Java中String类型与默认字符编码
-
Java Base64位编码与String字符串的相互转换,Base64与Bitmap的相互转换实例代码
-
解析JavaScript中的字符串类型与字符编码支持
-
详解.NET中string与StringBuilder在字符串拼接功能上的比较
-
js最实用string(字符串)类型的使用及截取与拼接详解
-
JAVA语法String字符串与StringBuilder使用详解
-
Java中Integer与String类型互转
-
java字符串在内存和文件中编码的不同,如何理解二进制与编码的关系
-
解析JavaScript中的字符串类型与字符编码支持
-
详解.NET中string与StringBuilder在字符串拼接功能上的比较