java中的编码

来源:https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/#icomments

在计算机用使用0、1来保存数据,存储的单位是字节(8bit/8位),每字节保存的最大数字是256,只保存英文可以,但是加上汉字就需要扩展了。

ASCII编码

  总共有128位,用一个字节的低7位表示,0-31是控制字条换行回车删除等,32-126是可打印字符。

ISO-8859-1

  ISO组织在ASCII码基础上又制定了一些列标准用来扩展ASCII编码,它们是ISO-8859-1~ISO-8859-15,其中ISO-8859-1涵不盖了大多数西欧字符。ISO-8859-1仍为单字节编码,共能表示256个字符。

GB2312

  全称叫《信息交换用汉字编码字符集基本集》,双字节编码,总范围是A1~F7,其中A1~A9是符号区,共包含682个符号。从B0~F7是汉字区,包含6763个汉字。

GBK

  全称叫《汉字内码扩展规范》,扩展GB2312,能表示21003个汉字,与GB2312兼容。

GB18030

  全称叫《信息交换用汉字编码字符集》,与GB2312兼容。国家标准,但使用中并不广泛。

UTF-16

  UTF-16具体定义了Unicode(Universal Code统一码)字符在计算机中存取方法。用两个字节来表示任何字符,共16个bit,所以叫UTF-16。Java以UTF-16作为内存的字符存储模式。

UTF-8

  UTF-16统一采用两个字节表示一个字符,虽然方便,但有很大一部分的字符用一个字节就可以表示的现在要用两个字节表示,存储空间放大了一倍。

  UTF-8采用了变长技术,规则如下:

  1、如果一个字节,最高位(第8位)是0,表示这是一个ASCII字条(00~7F)。可见,所有ASCII编码已经是UTF-8了。

  2、如果一个字节,以11开头,连续的1的个数暗示这个字符的字节数,例如:110xxxxx代表字是双字节UTF-8字符的首字节。

  3、如果一个字节,以10开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节。

 如下代码:打印出编码的16进制

public static void main(String[] args) {
        String test = "a 北京";
        System.out.println(Arrays.toString(test.getBytes()));
        printHex(test.getBytes());
        try {
            byte[] iso8859 = test.getBytes("ISO-8859-1");
            printHex(iso8859);
            byte[] gb2312 = test.getBytes("GB2312");
            printHex(gb2312);
            byte[] gbk = test.getBytes("GBK");
            printHex(gbk);
            byte[] utf16 = test.getBytes("UTF-16");
            printHex(utf16);
            byte[] utf8 = test.getBytes("UTF-8");
            printHex(utf8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    public static void printHex(byte[] array){
        for(byte aByte : array){
            System.out.print(Integer.toHexString(aByte & 0xFF) + " ");
        }
        System.out.println();
    }

输出结果:

[97, 32, -79, -79, -66, -87]
61 20 b1 b1 be a9
61 20 3f 3f
61 20 b1 b1 be a9
61 20 b1 b1 be a9
fe ff 0 61 0 20 53 17 4e ac
61 20 e5 8c 97 e4 ba ac

 1。System.out.println(Arrays.toString(test.getBytes()));默认打印出系统默认编码(GBK)的结果

  97 32 -79 -79 -66 -87(其中97对应ascii中的a,32对应ascii中的空格)

 2. printHex(test.getBytes()); 按16进制打印结果 61 20 b1 b1 be a9

3. "ISO-8859-1"编码将[b1 b1]转换为 3f, [be a9]转换为3f.ISO-8859-1是单字节编码,中文被转化成3f的byte,也就是“?”字符。中文字符经过ISO-8859-1编码会丢失信息,会把不认识的字符吸收掉。

4. "GB2312",英文字母保存为1个字节,汉字保存为两字节 北->[b1 b1],京 -> [be a9]

5."GBK" 编码同GB2312

6."UTF-16",每个字母或汉字都保存为两个字节.

  [fe ff 0 61 0 20 53 17 4e ac]结果中: [fe ff]表示 Big Endian。

    Big Endian:假设一个字符由两上字节来表示 0xabcd,那么在存储时是按[ab cd] 来存储还是按[cd ab]的顺利来存储。如果按[ab cd]来存储,则称为 big Endian, 如果存储按[cd ab],则称为 Little Endian。

  00 61 为字符"a", [00 20] 为空格, [53 17]代表UTF-16中的“北”,[4e ac]为“京”

7."UTF-8"结果:61 20 e5 8c 97 e4 ba ac

  其中 61的二进制为( 0110 0001)根据UTF-8的规则,首位为0,表示这是一个ASCII码,一个字节表示,得到“a",同理[20]得到空格。

  第三个字节e5二进制为(1110 1001)为111开头,表示这是一个三字节的开始。第四个字节 8c 二进制(1000 1100)表示为一个字节延续,第五个字节 97二进制为(1001 0111)。

    e5->1110 1001去除表示字节开始的前四位,得到 --> 1001,

    8c-> 1000 1100 去除表示顺序的前两位,得到--> 001100,

    97-> 1001 0111 去除表示顺序的前两位,得到--> 010111;

    将1001, 001100, 010111组合 [1001, 0011, 0001, 0111]得到16进制[53, 17]正好与UTF-8中的“北”相对应。

  同理,“e4 ba ac”代表“京”

在代码打印16进制的方法中

System.out.print(Integer.toHexString(aByte & 0xFF) + " ");

  一个Byte值与0xFF后调用Integer的toHexstring方法。原因在于若该byte值为负时,例: -79,Java的byte保存为1个字节,补码的结果为(1011 0001,16进制 0xb1),会强转为Java中的负数的int,java中的int保存为4字节(11111111 11111111 11111111 10110001,16进制为 0xffffffb1).

  在此处与0xFF后,会将int中的前三个字节中的1改为0,这样得到的结果就会为0xb1.

Integer中的toHexString()

  Integer中的tohexString, toBinaryString, toOctalString 都会调用方法toUnsignedString( int i, int shift),参数 shift的值,toBinaryString为1,toOctalString, toHexString为4.

private static String toUnsignedString(int i, int shift) {
	char[] buf = new char[32];
	int charPos = 32;
	int radix = 1 << shift;    //shift为4,相当于*2^4=8
	int mask = radix - 1;    //mask=7( 0000 1111)
	do {
          // i & mask 得到i的最未端四位二进行数字,例 i=25(0001 1001), i&mask=9(1001)
         //digits为数组,第9个得到char[9]=‘9‘
	    buf[--charPos] = digits[i & mask];
         // >>>为无符号位右移,高位补0. ps:25(0001 1001)向右移动4位得到1(0000 0001)
        // >> 为有符号位右移,若为正数,高位补0,若为负数,高位补1.
	    i >>>= shift;
	} while (i != 0);

	return new String(buf, charPos, (32 - charPos));
    }

  

时间: 2024-10-10 08:46:28

java中的编码的相关文章

关于java中的编码问题

GET方式提交的数据不会受页面编码的影响,应该都是以iso8859-1方式编码提交到后台程序,在后台java代码中可以通过 String str1=new String(name.getBytes("iso8859-1"),"UTF-8"); 的方式对字符串解码,解决乱码问题. 关于java中的编码问题,布布扣,bubuko.com

java中的编码问题

一直在试图搞清楚java中的编码问题,也看了网上的一些文章,但还是云里雾里.直到最近看了方立勋老师的web课程,才略略明白一点. 在此记录一下自己的理解,看看自己能不能说清楚. 第一个问题:我在java代码中定义了一个字符串,它是什么编码? 字符串实质是一个char数组.那么char的编码,其实就是字符串的编码.那么char什么编码呢?为什么'中'字转int类型后的值是20013呢? char c = '中'; System.out.println(c); // 中 System.out.pri

Java 中需要编码的场景

I/O 操作中存在的编码 我们知道涉及到编码的地方一般都在字符到字节或者字节到字符的转换上,而需要这种转换的场景主要是在 I/O 的时候,这个 I/O 包括磁盘 I/O 和网络 I/O,关于网络 I/O 部分在后面将主要以 Web 应用为例介绍.下图是 Java 中处理 I/O 问题的接口: Reader 类是 Java 的 I/O 中读字符的父类,而 InputStream 类是读字节的父类,InputStreamReader 类就是关联字节到字符的桥梁,它负责在 I/O 过程中处理读取字节到

JAVA中的编码分析

在实际编程中可以不用关注JVM中使用的是什么编码,而只需要关注自己输出需要采用的编码,JVM会根据你设置的编码正确操作. 1.String采用的是什么编码? 很多厂家根据规范实现了JVM,JVM只说明了String应该符合Unicode编码.Unicode编码只是一种编码模型,utf8,utf16,utf32都属于Unicode模型 ,具体的信息参阅http://www.cnblogs.com/YDDMAX/p/5360709.html 2.为什么JAVA中Char是两个字节? 参阅http:/

Java中字符编码和字符串所占字节数 .

首 先,java中的一个char是2个字节.java采用unicode,2个字节来表示一个字符,这点与C语言中不同,C语言中采用ASCII,在大多数 系统中,一个char通常占1个字节,但是在0~127整数之间的字符映射,unicode向下兼容ASCII.而Java采用unicode来表示字符,一个中文或英文字符的unicode编码都占2个字节,但如果采用其他编码方式,一个字符占用的字节数则各不相同. 在 GB 2312 编码或 GBK 编码中,一个英文字母字符存储需要1个字节,一个汉字字符存储

Java中需要编码的场景

一.I/O 操作中存在的编码 涉及到编码的地方一般都在字符到字节或者字节到字符的转换上,而需要这种转换的场景主要是在 I/O 的时候,这个 I/O 包括磁盘 I/O 和网络 I/O,关于网络 I/O 部分在后面将主要以 Web 应用为例介绍. 下图是 Java 中处理 I/O 问题的接口:       Reader 类是 Java 的 I/O 中读字符的父类,而 InputStream 类是读字节的父类,InputStreamReader 类就是关联字节到字符的桥梁,它负责在 I/O 过程中处理

java基础----&gt;java中字符编码问题(一)

这里面对java中的字符编码做一个总结,毕竟在项目中会经常遇到这个问题. 文件的编码格式 一.关于中文的二进制字节问题 public static String CHARSET_TEXT = "我爱LL"; // 打印字节的16进制表示 private void printBinarys(byte[] buffer) { for (byte b : buffer) { System.out.print(Integer.toHexString(b & 0xff) + "

java中关于编码的问题(字符转换流及字符缓冲流 )

上次我们使用的是字节流,还有一种方式就是字符流,上次说过如何分辨使用哪种流,如果记事本可以读懂则使用字符流,否则使用字节流.使用字符流就需要牵扯到编码的问题,下面给出一种转化流的格式. OutputStreamWriter OutputStreamWriter(OutputStream os):默认编码,GBK OutputStreamWriter(OutputStream os,String charsetName):指定编码.InputStreamReader InputStreamRead

还是java中的编码问题

用Java,linux我最恨的是编码问题, https://stijndewitt.wordpress.com/2010/05/05/unicode-utf-8-in-eclipse-java/ 上文建议将eclipse中全部设成utf-8: 但是我学习的书的样例代码使用的是GBK编码,在eclipse中打开时就是乱码了: 重新改成GBK,又正常了: 可以先用记事本打开,然后另存为,选择utf-8编码,这样也行.