从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • 计算机历史

  • 数字电路

  • 计算机组成原理

  • 汇编语言

  • C语言

  • 数据结构

  • 操作系统

  • Linux

  • 计算机网络

  • Git

  • 数据库

  • 计算机小知识

    • 简单聊聊计算机之中的时间
    • 简单聊聊字符编码
    • ASCII字符表和说明
    • ASCII的SOH的用处
    • 回车和换行
    • 汉字是怎么编码的
    • 简单聊聊Unicode
    • 手持两把锟斤拷,口中疾呼烫烫烫
    • 数据库与编码
    • 编程语言与字符编码
      • 一个字符占多少个字节?
      • Java中的字符串
      • char类型
      • Python下的字符编码
      • Java中的String.length()​
      • ​String.codePointCount()​
      • 代码
      • 参考
    • URL编码
    • Base64编码
    • 字符编码小结
    • literacy
  • 编译原理

  • 名人堂

  • 计算机基础
  • 计算机小知识
2022-12-21
目录

编程语言与字符编码

# 20.编程语言与字符编码

‍

聊聊在编程语言中的字符,例如Java

‍

# 一个字符占多少个字节?

得看情况,不同编码下情况不同。这里引用 肖国栋 (opens new window) 大佬的回答:

具体地讲,脱离具体的编码谈某个字符占几个字节是没有意义的。

就好比有一个抽象的整数“42”,你说它占几个字节?这得具体看你是用 byte,short,int,还是 long 来存它。用 byte 存就占一字节,用 short 存就占两字节,int 通常是四字节,long 通常八字节。当然,如果你用 byte,受限于它有限的位数,有些数它是存不了的,比如 256 就无法放在一个 byte 里了。字符是同样的道理,如果你想谈“占几个字节”,就要先把编码说清楚。

同一个字符在不同的编码下可能占不同的字节。

就以你举的“字”字为例,“字”在 GBK 编码下占 2 字节,在 UTF-16 编码下也占 2 字节,在 UTF-8 编码下占 3 字节,在 UTF-32 编码下占 4 字节。

不同的字符在同一个编码下也可能占不同的字节。

“字”在 UTF-8 编码下占3字节,而“A”在 UTF-8 编码下占 1 字节。(因为 UTF-8 是变长编码)

‍

‍

# Java中的字符串

对于String类型,有这样一个方法:getBytes()​,其将一个字符串转化为Byte序列,并存储到新的byte[]​数组

    String str2 = "abcdefg";
    byte[] b = str2.getBytes();
    for(int i = 0; i < b.length; i++){
      System.out.println(b[i]); //输出97.98.99.100...103, 就是abcdefg的ASCII码
  
}
1
2
3
4
5
6

‍

‍

问个面试题:new String("字").getBytes().length​的值是多少?还是上面提到的那句话,得看编码。

在UTF8下,"字"​占3个; 而在GBK下,一个汉字占2个字节;如果getBytes()​没有传参,那么默认使用操作系统编码,通常,Windows 系统下是 GBK,Linux 和 Mac 是 UTF-8.

String str = "严";
System.out.println("str.getBytes().length: "+ str.getBytes().length);
System.out.println("str.getBytes(\"GBK\").length: "+ str.getBytes("GBK").length);
System.out.println("str.getBytes(\"UTF-8\").length: "+ str.getBytes("UTF-8").length);
1
2
3
4

‍

编译和运行结果:

str.getBytes().length: 2
str.getBytes("GBK").length: 2
str.getBytes("UTF-8").length: 3
1
2
3

注意事项:

  1. 可以在启动JVM时设置一个默认编码,例如:java -Dfile.encoding=GBK Main​。不过如果你在代码里还是显示的指定了编码,还是以指定编码为准;
  2. 如果你用IDE来运行代码,并且设置了工程的默认编码是UTF-8,那么此时运行程序的时候会加上-Dfile.encoding=UTF-8​ 参数。
  3. 由于受启动参数及所在操作系统环境的影响,不带参数的 getBytes 方法通常是不建议使用的,最好是显式地指定参数以此获得稳定的预期行为。

‍

# char类型

Java语言规范规定,Java的char类型是UTF-16的code unit,也就是一定是16位(2字节);

官方文档 (opens new window): char​, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1 (opens new window)).

值得一提的是,在Java设计之初,UTF-16还是定长编码的,但是随着Unicode字符的增多,UTF-16就改为变长编码了(2个字节或4个字节)。 所以char 中只能放 UTF-16 编码下只占 2 字节的那些字符,如果一个字符在 UTF-16 编码下占 4 字节,显然它是不能放到 char 中的。

‍

‍

‍

# Python下的字符编码

Python2默认用的编码是ASCII,Python3默认用的是UTF8

分别使用len("你好") 在Python3得到的结果是2,在Python2得到的结果是6(6个字节)

‍

‍

‍

# Java中的String.length()​

在Java中,可以通过String.length()​ 计算字符串的长度。那么这个长度是什么呢?我们来看看length()​的注释和源码:

/**
 * Returns the length of this string.
 * The length is equal to the number of Unicode code units in the string.
 *
 * @return  the length of the sequence of characters represented by this object.
 */
public int length() {
    return value.length;
}
1
2
3
4
5
6
7
8
9

注释里说,会返回字符串中Unicode unit的数量。在Java中,使用的是UTF-16,因此这个方法的功能可以解释为:返回字符串的长度,这一长度等于字符串中的UTF-16的代码单元的数目。

也就是说,如果一个字符使用4个字节,那么String.length()​长度是2!

‍

我们来测试下

public class TestStringLength {
  public static void main(String[] args) {
    String str = "A";
    System.out.println(str.length());

    String str2 = "😀";
    System.out.println(str2.length());
  }
}
1
2
3
4
5
6
7
8
9

对于大多数emoji表情来说,其码点都比较大,得用4个字节,因此在UTF-16中就得用2个字节,因此结果分别输出1,2

不会输入emoji的可以参考我的博客:输入法的技巧 (opens new window)

‍

补充:String.length()​返回的是value.length​,这个value是什么呢?是一个char数组,前面我们也讲过Java的char类型是UTF-16的code unit,也就是一定是16位(2字节)

 private final char value[];
1

‍

‍

# ​String.codePointCount()​

那么我们如何统计字符串有几个字符呢?可以用​String.codePointCount()​​

文档说明:返回指定字符序列的文本范围内的 Unicode 代码点数量。

public class TestStringLength {
  public static void main(String[] args) {
    String str2 = "😂";
    System.out.println(str2.length());
    System.out.println(str2.codePointCount(0,str2.length())); //输出1
  }
}
1
2
3
4
5
6
7

# 代码

相关代码已上传到Gitee:01.JavaSE/05.OOP/15.character · 小林/LearnJava - 码云 - 开源中国 (opens new window)

‍

# 参考

Java 语言中一个字符占几个字节? - 知乎 (opens new window)

本文主要参考了肖国栋 (opens new window) 大佬的回答,根据自己的测试而成

‍

在GitHub上编辑此页 (opens new window)
上次更新: 2023/2/2 08:55:43
数据库与编码
URL编码

← 数据库与编码 URL编码→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式