当前位置: 首页 > news >正文

Java GBK中文乱码问题分析

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在io相关的操作中经常会出现乱码问题

 

比如在一个txt文件中按GBK编码保存内容"淘!我喜欢!"

033555_pykS_2630165.png

然后用RandomAccessFile类读取并打印一行。

RandomAccessFile raf = new RandomAccessFile("D:\\1.txt","r");
System.out.print(raf.readLine());

 

打印结果显示乱码:

033555_Ojoc_2630165.png

 

在网上查询到加入相关编码解码操作后可以解决该问题

RandomAccessFile raf = new RandomAccessFile("D:\\1.txt","r");
System.out.print(new String(raf.readLine().getBytes("ISO-8859-1"),"gbk"));

 

033555_SpeV_2630165.png

 

问题:

在这个过程中发生了什么?

 

要解答这个问题首先要知道编码和解码的概念以及产生的原因:

为什么要编码

 

不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言。由于人类的语言有太多,因而表示这些语言的符号太多,无法用计算机中一个基本的存储单元—— byte 来表示,因而必须要经过拆分或一些翻译工作,才能让计算机能理解。我们可以把计算机能够理解的语言假定为英语,其它语言要能够在计算机中使用必须经过一次 翻译,把它翻译成英语。这个翻译的过程就是编码。所以可以想象只要不是说英语的国家要能够使用计算机就必须要经过编码。这看起来有些霸道,但是这就是现 状,这也和我们国家现在在大力推广汉语一样,希望其它国家都会说汉语,以后其它的语言都翻译成汉语,我们可以把计算机中存储信息的最小单位改成汉字,这样 我们就不存在编码问题了。

 

所以总的来说,编码的原因可以总结为:

    1.计算机中存储信息的最小单元是一个字节即 8 个 bit,所以能表示的字符范围是 0~255 个。

    2.人类要表示的符号太多,无法用一个字节来完全表示。

    3.要解决这个矛盾必须需要一个新的数据结构 char,从 char 到 byte 必须编码。

名词解释:

解码:将byte数组转为char数组。

编码:将char数组转为byte数组。

 

计算机存储的基本单位是byte,但打开一个文件时文件编辑器已经做了解码的工作。

以下为解码过程描述

033555_qiHZ_2630165.png

文件实际存储的内容是(以下为16进制):

033555_0bv2_2630165.png

打开文件后看到的内容为

033555_u3VY_2630165.png

需要详细说明以下代码的处理过程

RandomAccessFile raf= new RandomAccessFile("D:\\1.txt","r");
System.out.print(raf.readLine());

 

首先看一下java.io.RandomAccessFile#readLine方法的源码

public final String readLine() throws IOException {
        StringBuffer input = new StringBuffer();
        int c = -1;
        boolean eol = false;
        while (!eol) {
            switch (c = read()) {
            case -1:
            case '\n':
                eol = true;
                break;
            case '\r':
                eol = true;
                long cur = getFilePointer();
                if ((read()) != '\n') {
                    seek(cur);
                }
                break;
            default:
                input.append((char)c);
                break;
            }
        }
        if ((c == -1) && (input.length() == 0)) {
            return null;
        }
        return input.toString();
    }

 

主要关注read()部分和(char)c,read()是一个本地方法,作用是从文件中读取一个byte字节。

033555_PrZ5_2630165.png

(char)c是将变量c从byte类型转换为char类型,这是一个解码操作。

问题:此处是以什么格式进行解码?

解码格式是ISO-8859-1

raf.readLine()的处理过程如下

033555_kD4Z_2630165.png

那么

new String(raf.readLine().getBytes("ISO-8859-1"),"gbk")

 

这行代码做了什么

首先readLine()按行一字节一字节地读取文件中的数据,并且按ISO-8859-1进行解码拼成char数组,然后getBytes("ISO-8859-1")对拼成后的char数组按ISO-8859-1进行编码获取byte数组,最后new String(string,"gbk")对编码后的byte数组用gbk格式进行解码成char数组。

 

参考资料:深入分析 Java 中的中文编码问题

 

遗留问题:

1、如何避免重复转码。

2、RandomAccessFile的readLine()效率非常低,如何提高效率。

 

 

JAVA后端qq交流群:477318923

8fd463cd593acdd85b8c4f696da17078f32.jpg

转载于:https://my.oschina.net/skyshitt/blog/614439

相关文章:

  • 巧用位运算求解二进制中1的个数
  • Linux Netcat 命令——网络工具中的瑞士军刀
  • python学习笔记-Day14 -js/dom/jquery
  • C++构造函数详解及显式调用构造函数
  • web应用中log4j应用--log4j.xml同时输出多种日志
  • apache的动态和静态
  • Navicat 结构同步常规设置讲解
  • hbase参考官方文档搭建完全分布式环境遇到的问题
  • 【设计模式】GoF设计模式学习总结
  • 毛毛雨的博客乐园—内容简介
  • Android布局— — —表格布局
  • Linux统计文件/目录数量ls -l | grep ^- | wc -l匹配开头和结尾
  • 老男孩28期运维张帅学习Linux决心书
  • Mongo读书笔记2 -- 数据类型
  • OC----简单的购物系统----
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 2017-09-12 前端日报
  • nginx 负载服务器优化
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • NSTimer学习笔记
  • SOFAMosn配置模型
  • Transformer-XL: Unleashing the Potential of Attention Models
  • ucore操作系统实验笔记 - 重新理解中断
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • Xmanager 远程桌面 CentOS 7
  • 基于webpack 的 vue 多页架构
  • 将 Measurements 和 Units 应用到物理学
  • 你不可错过的前端面试题(一)
  • 前端技术周刊 2019-02-11 Serverless
  • 全栈开发——Linux
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #define 用法
  • #HarmonyOS:基础语法
  • #QT(TCP网络编程-服务端)
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (二)linux使用docker容器运行mysql
  • (分布式缓存)Redis持久化
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)计算机毕业设计ssm电影分享网站
  • (三)c52学习之旅-点亮LED灯
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)LINQ之路
  • **python多态
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .net MVC中使用angularJs刷新页面数据列表
  • .Net6 Api Swagger配置
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • @Service注解让spring找到你的Service bean
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限