前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从byte[]和char[]的不同,看字符串的编码问题

从byte[]和char[]的不同,看字符串的编码问题

作者头像
品茗IT
发布2023-10-22 15:12:30
3070
发布2023-10-22 15:12:30
举报
文章被收录于专栏:品茗IT品茗IT

从byte[]和char[]的不同,看字符串的编码问题

一、概述

众所周知:

  1. byte 是字节数据类型 ,是有符号型的,占1 个字节;大小范围为-128—127 。
  2. char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 );大小范围 是0—65535 ;

char是一个16位二进制的Unicode字符,JAVA用char来表示一个字符 。

可能看到上面这句话的时候,往往不会在意char是不是Unicode字符,当时它却是我们理清楚编码的关键。

二、编码类型

一说到编码,就会想到GBK和utf8,到底这些编码都是干什么的呢?

  1. ASCII:严格来说,我们提到编码的时候,没必要说ASCII的,因为它不支持中文,它就不会被我们日常拿来用做字符串的编码。它对应的Charset是US-ASCII
  2. GBK:国人就定义了一套编码规则,中文两个字节,英文一个字节,注意是字节。它对应的Charset是GBK。
  3. UTF-8:UTF是 Unicode Translation Format,即把Unicode转做某种格式的意思,针对Unicode的一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,中文三个字节,英文一个字节。它对应的Charset是UTF-8。
  4. Unicode:Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。UTF-8是Unicode的实现方式之一。如果用Charset.forName("Unicode"),结果是UTF_16。

三、byte[]和char[]

byte[]是字节数组,而char[]是字符数组。

  1. 一个英文,存储在byte[]中,长度是1,存储在char[]也是1。
  2. 一个中文,存储在byte[]中,utf8长度是3,存储在char[]是1。
3.1 String和StringBuilder看字节数组和字符数组

String的构造方法有根据字符数组和字节数组创建字符对象,StringBuilder中只有添加字符数组的方法。 String:

代码语言:javascript
复制
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
public String(byte bytes[]) {
    this(bytes, 0, bytes.length);
}
public String(byte bytes[], String charsetName)
            throws UnsupportedEncodingException {
    this(bytes, 0, bytes.length, charsetName);
}
public String(byte bytes[], Charset charset) {
    this(bytes, 0, bytes.length, charset);
}

StringBuilder:

代码语言:javascript
复制
public StringBuilder append(char[] str) {
    super.append(str);
    return this;
}

所以,有时候会疑惑,为什么StringBuilder不需要考虑编码的问题,这是因为StringBuilder本身是一个char[] value.

而String本身也是个char value[],但是却将byte[]装成了char[]:

代码语言:javascript
复制
static char[] decode(String charsetName, byte[] ba, int off, int len)
        throws UnsupportedEncodingException
{
    StringDecoder sd = deref(decoder);
    String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
    if ((sd == null) || !(csn.equals(sd.requestedCharsetName())
                          || csn.equals(sd.charsetName()))) {
        sd = null;
        try {
            Charset cs = lookupCharset(csn);
            if (cs != null)
                sd = new StringDecoder(cs, csn);
        } catch (IllegalCharsetNameException x) {}
        if (sd == null)
            throw new UnsupportedEncodingException(csn);
        set(decoder, sd);
    }
    return sd.decode(ba, off, len);
}

所以,字符串就是存储的字符,不叫字节串,字节转字符需要指定编码,字符转字节也需要指定编码。

3.1 InputStream和InputStreamReader看字节数组和字符数组

InputStream无论是网络流还是文件流,都是不需要自定编码,如:

代码语言:javascript
复制
public FileInputStream(String name) throws FileNotFoundException {
    this(name != null ? new File(name) : null);
}
public ByteArrayInputStream(byte buf[]) {
    this.buf = buf;
    this.pos = 0;
    this.count = buf.length;
}

因为它本身就是字节,属于存储属性的字节,已经有编码含义。

InputStreamReader需要指定编码:

代码语言:javascript
复制
public InputStreamReader(InputStream in, String charsetName)
        throws UnsupportedEncodingException
{
    super(in);
    if (charsetName == null)
        throw new NullPointerException("charsetName");
    sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
}

类似与String, 它需要将字节转成字符,就需要指定编码。

四、结论

一个字就是一个字符,一个字可以有多个字节。不同的编码下,一个字的字节数不同。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-07-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 从byte[]和char[]的不同,看字符串的编码问题
  • 一、概述
  • 二、编码类型
  • 三、byte[]和char[]
    • 3.1 String和StringBuilder看字节数组和字符数组
      • 3.1 InputStream和InputStreamReader看字节数组和字符数组
      • 四、结论
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档