从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • 计算机简史

  • 数字电路

  • 计算机组成原理

    • 计算机组成原理(北大-陆俊林)

    • 字符编码入门

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

  • Linux

  • 计算机网络

  • 数据库

  • 编程工具

  • 装机

  • 计算机基础
  • 计算机组成原理
  • 字符编码入门
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

问个面试题: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 (opens new window):https://gitee.com/peterjxl/LearnJava/tree/master/src/01.JavaSE/05.OOP/15.character (opens new window)

上次更新: 2025/5/5 17:15:09
数据库与编码
URL 编码

← 数据库与编码 URL 编码→

最近更新
01
2025 年 4 月记
04-30
02
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
03
一个小技巧,让电子书阅读体验翻倍!
04-18
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式