字符编码

本文深入浅出地介绍了计算机中字符编码的基本概念,包括ASCII、ISO8859-1、GB2312、GBK、GB18030、UTF-8等常见编码的区别与联系,以及如何在Java Web环境中正确处理中文乱码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

乱码问题

乱码问题是开发中经常碰到的问题,每次遇到这种问题都是从网上搜解决方案,然后拷贝代码去试,不行再去找,成功解决就放一边了,开发完成后也不去追究究竟是什么原因造成的乱码问题,只知道是编码问题,但如果进一步问,是什么样的编码问题导致的就不得而知了。
其实编码没有那么深奥,可以这样理解:计算机在存储字符时,使用的是二进制的数字,为了存储字符,就需要制定一套规则用于将二进制的数字与字符一一对应起来,这样形成的一套规则就叫编码规则,而这套规则包含的所有字符组成一个字符集。那么,在使用该编码规则对将字符转换成二进制存储起来,那么当需要取字符时,很显然也只能使用这套规则就二进制数字进行解码。那么乱码的原因就是因为编码和解码使用了不同的编码规则,并且解码使用的编码规则不兼容编码时编码规则,导致二进制数字不能被正常解析,出现乱码。
有了这样的理解后,接下来就需要了解下常用的编码规则都有哪些,这些规则之间的不同之处是什么。

编码及字符集

  • ASCII及ISO8859-1

    ASCII是美国信息交换标准代码的英文(American Standard Code for Information Interchange)首字母缩写,使用单字节表示一个字符,总共有7位,表示的字符集有128个字符。ISO8859-1是ASCII的扩展字符集,也是单字节编码,但是使用了8位来表示,字符集中有256个字符。按照字符的二进制数字大小排列,前128个字符完全相同,因此使用ASCII编码的字符可以使用ISO8859-1进行解码。

  • GB及GBK

    GB及GBK是适用于汉字的编码方式,按照时间先后主要有以下几种:
    • GB2312 中国国家标准简体中文字符集,收录了6763个汉字。采用2个字节来表示,规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节。
    • GBK 汉字内码扩展规范,K为汉字“扩展”的拼音首字母大写。是GB2312的扩展,汉字和字符更多,向下完全兼容GB2312,因此使用GB2312编码的汉字,可以使用GBK进行解码。
    • GB18030 国家标准 GB-18030-2005《信息技术中文编码字符集》是最新的内码集,有70244个汉字,向下完全兼容GB2312和GBK。多字节编码,单字节双字节和四字节。

    以上三种的0-128与ASCII完全一致,即兼容ASCII编码

  • UTF-8/UTF-16
    • UTF-8 8-bit Unicode Transformation Format ,可变长度字符编码,与ASCII兼容。

Java Web中的编解码

Java的网络通信采用ISO8859-1编码方式,因此HTTP请求在传递之前都要经过ISO8859-1编码后进行传输,而后在接收端再使用ISO8859-1进行解码。比如传递一个参数是中文,中文是GBK编码的,将参数使用GBK编码后,再使用ISO8859-1解码。解码后进行传输,浏览器接收后使用GBK进行编码,再使用ISO8859-1进行解码,得到正确的字符。整个过程如下面的代码所示:

    public static void main(String[] args) throws UnsupportedEncodingException {

        String s = "你好";  
         
        //服务器端,对汉字字符串进行GBK编码,再使用ISO8859-1进行解码,传输解码后的字符串
        // 编码  
        byte[] gbk = s.getBytes("gbk");  
        // 解码 
        String s3 = new String(gbk, "iso8859-1");
           
        //客户端接收到上s3后,先使用iso8859-1进行编码,再使用gbk进行解码,得到原始字符
        s3 = new String(s3.getBytes("iso8859-1"), "gbk");  
          
        System.out.println(s3);  
            
    }

如果不进行上述操作时,直接传递字符串s,相当于直接传递的是s的ISO8859-1的编码,那么浏览器在接收到s的ISO8859-1的编码后,无论使用任何解码方式都没办法正常解码,出现乱码:

    public static void main(String[] args) throws UnsupportedEncodingException {
        
        //服务器端对s不做任何处理,网络传输时s会被按照iso8859-1进行编码
        String s = "你好";  
        
        //客户端接收到上s的编码二进制后,无论使用GBK还是UTF-8或者其他任一一种编码方式都无法解析出正确的s
        String s3 = new String(s.getBytes("iso8859-1"), "iso8859-1");
        String s4 = new String(s.getBytes("iso8859-1"), "GBK");
        String s5 = new String(s.getBytes("iso8859-1"), "UTF-8");
          
        System.out.println(s3);
        System.out.println(s4);
        System.out.println(s5);
            
    }

所以,在服务器端在发送汉字时,最稳妥的办法时,对汉字使用GBK或者UTF-8(UTF-8字符集也包含汉字)进行编码,最好是使用UTF-8进行编码因为有些浏览器比如Safari不支持GBK而UTF-8大多都支持,再使用ISO8859-1进行解码。这样汉字乱码问题就解决了。

1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值