java中的编码与解码

char

java的char类型占用两个字节,有三种赋值方式:

1、直接赋值

char c ='a';
char c1='中';
System.out.println(c); // a
System.out.println(c1); // 中

2、使用16进制或十进制赋值(这里的值是指编码表中对应的数值)

char c2= 0x8d24;
char c3 = 36132;
System.out.println(c2); // 贤
System.out.println(c3); // 贤

3、使用unicode码赋值

其中\表示转义,\u表示后面的数字为unicode码

char c4 = '\u8d24';
System.out.println(c4); // 贤

4、char是两个字节,只能表示utf-16中的基本面的字符,但是辅助面是由四个字节组成,所以只能用String表示

String c5 = "\ud842\udfb7";
System.out.println(c5); // 𠮷

String的编码和解码

编码

String的编码可以使用getBytes方法:

public static void main(String[] args) {
    String str = "芊雨";
    byte[] bytes = str.getBytes();
    for (int i = 0; i < bytes.length; i++) {
        System.out.printf("0x%x ", bytes[i]);
    } // 0xe8 0x8a 0x8a 0xe9 0x9b 0xa8 
}

可见一个汉字占三个字节,在IDEA中String的getBytes默认使用utf-8来编码

查看源码可知getBytes内部调用encode方法
encode
encode方法使用默认编码:
defaultCharset
默认编码从一个叫做file.encoding的属性中读取
file.encoding
所以我们修改了file.encoding属性,也就修改了编码
设置参数
此时一个汉字就占用两个字节了
运行结果

我们还可以直接在getBytes的参数中传入编码方式,来自定义编码

public static void main(String[] args) throws UnsupportedEncodingException {
    String str = "芊雨";
    byte[] b1 = str.getBytes("UTF-8");
    System.out.println(Arrays.toString(b1)); // [-24, -118, -118, -23, -101, -88]
    byte[] b2 = str.getBytes("GBK");
    System.out.println(Arrays.toString(b2)); // [-36, -73, -45, -22]
}
解码

String的解码可以使用构造函数

public static void main(String[] args) throws UnsupportedEncodingException {
    byte[] b1 = {-24, -118, -118, -23, -101, -88};
    byte[] b2 = {-36, -73, -45, -22};
    System.out.println(new String(b1)); // 芊雨
    System.out.println(new String(b1, "UTF-8")); // 芊雨
    System.out.println(new String(b2, "GBK")); // 芊雨
}
可逆编码
public static void main(String[] args) throws UnsupportedEncodingException {
    String str = "芊雨";
    byte[] b1 = str.getBytes("GBK");
    String str2 = new String(b1, "UTF-8");
    System.out.println(str2); // ܷ��
    String str3 = new String(b1, "GBK");
    System.out.println(str3); //芊雨
}

虽然上面使用GBK编码之后的字符串,使用UTF-8进行了解码。但是底层字节没有发生变化,所以可以还原成功

不可逆编码
public static void main(String[] args) throws UnsupportedEncodingException {
    String str = "芊雨";
    byte[] b1 = str.getBytes("ISO-8859-1");
    System.out.println(Arrays.toString(b1)); // [63, 63]
    String str2 = new String(b1, "ISO-8859-1");
    System.out.println(str2); // ??
}

上面虽然编码和解码都是使用的ISO-8859-1,但是由于ISO-8859-1不支持中文,所以在编码的时候使用?作为替换,这时候底层的字节已经发生变换,所以,解码之后只会出现?

解码问题
public static void main(String[] args) throws UnsupportedEncodingException {
    String str = "芊雨";
    byte[] b1 = str.getBytes("GBK");
    System.out.println(Arrays.toString(b1)); // [-36, -73, -45, -22]
    String str2 = new String(b1, "UTF-8");
    System.out.println(str2); // ܷ��
    byte[] b2 = str2.getBytes("UTF-8");
    System.out.println(Arrays.toString(b2)); // [-36, -73, -17, -65, -67, -17, -65, -67]
    String str3 = new String(b2, "GBK");
    System.out.println(str3); // 芊锟斤拷
}

上面的例子中GBK编码之后的字符串,使用UTF-8解码,UTF-8识别不了,于是就替换成了类似实心问号的字符。再进行UTF-8编码,实际上是对实心问号字符的编码,这个时候底层字节数组已经发生变化,自然会解码失败

public static void main(String[] args) throws UnsupportedEncodingException {
    String str = "芊雨";
    byte[] b1 = str.getBytes("GBK");
    System.out.println(Arrays.toString(b1)); // [-36, -73, -45, -22]
    String str2 = new String(b1, "ISO-8859-1");
    System.out.println(str2); // Ü·Óê
    byte[] b2 = str2.getBytes("ISO-8859-1");
    System.out.println(Arrays.toString(b2)); // [-36, -73, -45, -22]
    String str3 = new String(b2, "GBK");
    System.out.println(str3); // 芊雨
}

同样的方法,换成ISO-8859-1就不会出现上面的问题,是因为ISO-8859-1编码每一个字节多对应一个字符,不会出现有字符无法对应的情况,就是说底层字节数组没有发生变化

字符流编码与解码

字符流的编码与解码要注意的是:文件的编码和读取时使用的编码必须一致

// 文件:a.txt 编码:UTF-8 内容:芊雨
public static void main(String[] args) throws IOException {
    InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt"), "UTF-8");
    int ch;
    while ((ch = in.read()) != -1) {
        System.out.print((char) ch);
    } // 芊雨
    in.close();
}
使用字符流复制图片
public static void main(String[] args) throws IOException {
    InputStreamReader in = new InputStreamReader(new FileInputStream("a.png"), "UTF-8");
    OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("b.png"), "UTF-8");
    int ch;
    while ((ch = in.read()) != -1) {
        out.write(ch);
    }
    in.close();
    out.close();
}

这种图片复制方式会出现以下结果:b.png比a.png大,而且b.png文件损坏
复制结果
因为输入流根据UTF-8解码的时候会遇到不可表示的字符,就使用实心问号代替。这样就造成了字节流发生改变。

解决方法:将编码改为ISO-8859-1即可使用字节流复制图片

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值