Java中的UTF-8、UTF-16编码字符所占字节数
2017-05-01 23:19
633 查看
前言:上一篇文章写了关于Unicode,以及utf-8、utf-16相关知识。所以本篇博文来验证在java环境下,字符在不同编码下所占的字计数。
测试代码如下:
运行结果如下:
在前一篇文章的基础上,我们来分析一下运行结果。
“中”字的unicode码值为4E2D,使用UTF-8编码占3个字节。由于该字符位于BMP内,所以使用UTF-16编码应该占2个字节,但是运行结果为4个字节。
第二个字符(csdn编辑器不支持该字符的显示),该字符使用UTF-8应该占4个字节,运行结果正确。由于该字符位于BMP外,所以使用UTF-16编码应该占4个自己,但是运行结果显示占用了6个字节。
英文字母a,UTF-8编码应该和ASCII编码相同占用一个字节,运行结果显示占用一个字节。a在Unicode中位于BMP内,所以UTF-16编码应该占用4个字节,但是运行结果缺显示4个字节。
按照上面的运行结果,a在UTF-8编码下占用1个字节,在UTF-16编码下占用4个字节。那么猜测两个英文字母a,即”aa“在UTF-8和UTF-16编码下应该分别占2个和8个字节,但是运行结果却和想象中的不一样,aa在UTF-16编码下工占6个字节。
运行结果好像和上一篇中讲到的有点不相符啊!为什么会出现这样的结果的?
通过搜索相关文章,了解到java的字节码文件(.class)文件采用的是UTF-8编码,但是在java 运行时会使用UTF-16编码。在转码的时候会在前面加上表示字节顺序的字符,这个字符称为”零宽度非换行空格”(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。FEFF占用两个字节,所以就解释了为什么java环境下英文字母a在UTF-16编码占3个字节。
我们不妨将这些字符的在不同编码下的二进制转换为16进制并打印出来。
将代码修改如下:
运行结果:
测试代码如下:
package string; public class CharByteTest { public static void main(String[] args) throws Exception { // 第二个字符为BMP之外的字符,csdn编辑器无法显示该字符,可以在运行结果截图中看到 String[] strArr = {"中", "��", "a", "aa"}; String[] charsetArr = {"gbk", "utf-8", "utf-16", "gb2312"}; for(String str : strArr) { System.out.println(str); for(String charset : charsetArr) { byteTest(str, charset); } System.out.println("============================"); } } public static void byteTest(String str, String charset) throws Exception { System.out.println("编码:" + charset + "\t所占字节数:" + str.getBytes(charset).length); } }
运行结果如下:
在前一篇文章的基础上,我们来分析一下运行结果。
“中”字的unicode码值为4E2D,使用UTF-8编码占3个字节。由于该字符位于BMP内,所以使用UTF-16编码应该占2个字节,但是运行结果为4个字节。
第二个字符(csdn编辑器不支持该字符的显示),该字符使用UTF-8应该占4个字节,运行结果正确。由于该字符位于BMP外,所以使用UTF-16编码应该占4个自己,但是运行结果显示占用了6个字节。
英文字母a,UTF-8编码应该和ASCII编码相同占用一个字节,运行结果显示占用一个字节。a在Unicode中位于BMP内,所以UTF-16编码应该占用4个字节,但是运行结果缺显示4个字节。
按照上面的运行结果,a在UTF-8编码下占用1个字节,在UTF-16编码下占用4个字节。那么猜测两个英文字母a,即”aa“在UTF-8和UTF-16编码下应该分别占2个和8个字节,但是运行结果却和想象中的不一样,aa在UTF-16编码下工占6个字节。
运行结果好像和上一篇中讲到的有点不相符啊!为什么会出现这样的结果的?
通过搜索相关文章,了解到java的字节码文件(.class)文件采用的是UTF-8编码,但是在java 运行时会使用UTF-16编码。在转码的时候会在前面加上表示字节顺序的字符,这个字符称为”零宽度非换行空格”(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。FEFF占用两个字节,所以就解释了为什么java环境下英文字母a在UTF-16编码占3个字节。
我们不妨将这些字符的在不同编码下的二进制转换为16进制并打印出来。
将代码修改如下:
package string; public class CharByteTest { private static char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; public static void main(String[] args) throws Exception { String[] strArr = {"中", "��", "a", "aa"}; //String[] charsetArr = {"gbk", "utf-8", "utf-16", "gb2312"}; String[] charsetArr = {"unicode", "utf-8", "utf-16", "utf-16BE", "utf-16LE"}; for(String str : strArr) { System.out.println(str); for(String charset : charsetArr) { byteTest(str, charset); } System.out.println("============================"); } } public static void byteTest(String str, String charset) throws Exception { byte[] strByte = str.getBytes(charset); System.out.println("编码:" + charset + "\t所占字节数:" + strByte.length + "\t16进制:" + bytesToHexStr(strByte)); } // 将byte[]用十六进制字符串 public static String bytesToHexStr(byte[] bytes) { int index = 0; char[] hexChar = new char[bytes.length * 2]; for(int i = 0; i < bytes.length; i++) { hexChar[index++] = HEX_CHAR[bytes[i] >> 4 & 0xF]; hexChar[index++] = HEX_CHAR[bytes[i] & 0xF]; } return new String(hexChar); } }
运行结果:
相关文章推荐
- JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
- JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
- JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
- [转]字符编码,ansi, unicode,utf-8, utf-16
- 字符编码:Unicode/UTF-8/UTF-16/UCS/Endian/BMP/BOM
- [转]字符编码,ansi, unicode,utf-8, utf-16
- JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
- 第二篇:JAVA字符编码系列二:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换
- JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
- 第一篇:JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
- 用java程序将GBK字符转成UTF-8编码格式(转)
- JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
- 用java程序将GBK字符转成UTF-8编码格式
- JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础[引]
- JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
- java中的字符,字节和编码
- JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
- JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
- JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
- JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础