`

中文编码笔记

阅读更多
问题描述:

上周在压缩tar格式文件的时候, 遇到了乱码问题。
既是文件名在tar文件中显示为乱码。 如下图所示



你好被转换成了浣犲ソ

为什么会这样, 首先要了解一下中文编码。

国标码和unicode
国家标准强制标准冠以“GB”。现时中华人民共和国官方强制使用GB 18030标准,但较旧的计算机仍然使用GB 2312。
正如chrome浏览器里面所显示的三种中文编码-> utf-8, gbk, gb18030.
个人感觉一般开发都使用utf8和gbk编码。
而 "你好"->"浣犲ソ" 在这里也正是使用gbk标准来解码utf8编码文字所产生的错误。


GBK和Unicode的编码表
utf8:http://blog.csdn.net/qiaqia609/article/details/8069678
gbk: http://ff.163.com/newflyff/gbk-list/

这里就查看“你”这个汉字是怎么编码的。 在GBK中。对应的是C4 E3,而在utf-8中,对应的是E4 BD A0。
(注:最初我以为gbk的编码和utf8的编码之间会有一定的联系,一直在找它们的规律。结果发现, 我完全想错了。 他们的编码是没有什么可以转换的关系的。后面再说)

编码解码过程
上述编码全部都是十六进制的数字。 这里说一下编码解码的过程,拿
String str="你" 为例,先看一下文字是如何转换为二进制的。
GBK:
String gbk="你";
		
		byte[] bytes=gbk.getBytes("gbk");
		
		System.out.println(bytes.length);
		
		for(int i=0;i<bytes.length;i++){
			System.out.println(bytes[i]);
			int code= bytes[i]+256;
			System.out.println(code);//C4 E3
		}

这里的重点是方法 getBytes(Charset charset)。
该方法说明如下:
Encodes this String into a sequence of bytes using the named charset, storing the result into a new byte array.
所以byte[] bytes=gbk.getBytes("gbk")就将“你”这个汉字根据gbk编码标准,转换成了二进制的byte对象,放入byte[] bytes中。

后面的Integer.toHexString(code).toUpperCase()就会输出两个二进制字节所对应的十六位数字, 也就是C4 E3, 既GBK编码标准表中的“你”的区域位置。


那么软件又是如何解码的呢?
假如在上面的代码后面加入:
String gbk2=new String(bytes);
		System.out.println(gbk2);

运行程序,就会看到这里输出的是 ��。
原因就是,程序在编码的时候用的是gbk标准,产生了16位长度的二进制数字。
而我们的class文件的格式是utf-8的, 当使用new String(bytes)时,程序会默认使用utf8标准来进行解码。 这样自然不能正确的解码gbk格式的二进制数字。

就好比我们用realplayer去播放mkv格式的视频,是无法播放的, 因为realplayer不知道如何去解码mkv格式。

解决办法很简单,查看String的构造函数,就能看到
java.lang.String.String(byte[] bytes, String charsetName) throws UnsupportedEncodingException

Constructs a new String by decoding the specified array of bytes using the specified charset. The length of the new String is a function of the charset, and hence may not be equal to the length of the byte array.


通过使用特定编码来解码bytes数组来创建一个String对象。
因此只要使用
String gbk2=new String(bytes,"gbk");
		System.out.println(gbk2);

运行程序,就能看到正确的“你”的显示了。
因为程序调用了GBK标准,并以正确的解码方法,既两个字节表示一个汉字,来查找GBK标准表中所对应的汉字,就找到了“你”。


系统默认编码
我们的系统默认是使用unicode标准对文件进行编码解码的。
以win7为例, 打开控制面板->区域和语言-》管理, 可以看到:


所谓非Unicode程序所使用的语言, 既是当我们打开一个程序,而该程序所使用的编码不是Unicode, 这时候系统要使用的解码方法。

举个例子, 我们要打开一个日文软件,该日文软件并不是使用的utf8编码,而是其它的日本本地的编码, 这时候系统便会调用我们在这里所设置的非Unicode程序所使用的语言。 我猜大概就是GBK GB之类的。 于是我们就能看到满屏的乱码。
因此我们如果把这里修改为 日本(日语),重启电脑再打开该日文软件,就会正确显示日文了。 原因也就是系统用正确的编码标准来解码了。



tar文件名乱码问题
回到最初遇到的问题。我在网上查了很久, 最后看到
http://www.dewen.org/q/4494/ 这里说tar压缩格式不会记录字符集, 而rar和zip会。   如果这样的话, 那tar真是不适合中文。

具体来说就是, 文件名被压缩程序设置了utf8编码, 但是到了tar中, tar不支持utf8,于是我们的系统就使用了非Unicode程序所使用的语言来进行解码。
于是呢, 就有了以下步骤:


1. 定义了一个字符“你”, 然后该字符被用'utf8'编码, 变成了2进制11100100,10111101,10100000
之后此二进制被传入了某一个程序中, 该程序不知道‘你’这个字是什么编码格式的, 于是尝试用gbk进行解码。
GBK是怎么解码的呢? 会把这段二进制当做每16位表示一个字符。
于是前面的11100100,10111101就被提取了出来, 然后程序开始在GBK编码表中搜索对应的字符。
结果就找到了 E4 BD->浣 。
接下来的10100000没法解码, 就出来了一个问号'?'。


这段话是之前做的笔记, 也就是系统使用国标码标准来解码utf-8编码文字所出现的问题。




最后放上tar文件压缩的问题代码。


System.out.println(System.getProperty("file.encoding"));
		System.out.println(Charset.defaultCharset().name());
		
		
		String path="D:\\_thumbnail";
		String f="d:\\t.tar";
		TarArchiveOutputStream taos=new TarArchiveOutputStream(new FileOutputStream(f),"utf-8");//这里设置为GBK就可以解决乱码问题
		
		
		
		File of=new File(path);
		
		File[] ofs=of.listFiles();
		System.out.println(ofs.toString());
		for(File off:ofs){
			String parent=off.getParentFile().getParent(); //D:/
			String parent_relative=off.getParentFile().getAbsolutePath().substring(parent.length());
			
			FileInputStream fis=new FileInputStream(off);
			System.out.println(File.separator);
			TarArchiveEntry tae=new TarArchiveEntry(parent_relative+File.separator+new String(off.getName().getBytes("utf-8")));//这里的参数是压缩文件里的路径,也就是文件夹和文件名
															//比如_thumbnail/1.jpg,就会产生一个_thumnbnail的文件夹和一个1.jpg的文件。
			tae.setSize(off.length());
			taos.putArchiveEntry(tae);
			
			IOUtils.copy(fis, taos);
			fis.close();
			taos.closeArchiveEntry();
		}



TarArchiveOutputStream taos=new TarArchiveOutputStream(new FileOutputStream(f),"utf-8");//这里设置为GBK就可以解决乱码问题

Constructor for TarInputStream.

Parameters:
os the output stream to use
encoding name of the encoding to use for file names



如注释写的一样, 这里不写编码格式,则会使用默认的utf-8来进行文件名编码。
之所以设置GBK编码不会出现乱码,就是因为系统得不到tar压缩文件名的编码信息,就采用了非Unicode所使用语言,既GBK, 来进行解码。


解决方法:
压缩tar文件时,文件名用英文即可。

终于写完了-O- 写的不是一般的乱

  • 大小: 23.6 KB
  • 大小: 47.2 KB
分享到:
评论

相关推荐

    JavaFX+Jfoenix 学习笔记(十)--系统托盘及解决中文乱码问题源码

    JavaFX+Jfoenix 学习笔记系列文章的JavaFX+Jfoenix 学习笔记(十)--系统托盘及解决中文乱码问题源码

    MLX90640开发笔记(完整十章20191012).pdf

    本文件是MLX90640的产品开发笔记,包含了基本资料下载、中文资料、驱动移植、操作流程、计算方法、注意事项、插值处理、伪彩编码。 共分为十章 MLX90640开发笔记(一)概述及开发资料准备 MLX90640开发笔记(二)API...

    字符编码笔记:ASCII-Unicode和UTF-8

    字符编码笔记:ASCII-Unicode和UTF-8 字符编码笔记:ASCII-Unicode和UTF-8 字符编码笔记:ASCII-Unicode和UTF-8

    Java学习笔记

    5、如何处理中文乱码问题 6、使用JavaMail发送注册验证邮件 7、不安全的用户名密码验证 8、用Session保存登录信息 9、面向对象分析通常分为三个步骤 10、使用DataSource接口连接数据源 11、避免表单重复提交的技术 ...

    ExtJS4中文教程2 开发笔记 chm

    Javascript 汉字编码转换 Javascript 面向对象之封装 Javascript 面向对象之构造函数的继承 Javascript 面向对象之非构造函数的继承 JavaScript对象与继承教程之内置对象(下) JavaScript对象及继承教程(上) ...

    JAVAWeb全课程笔记( html版)

    [总结]JavaWeb乱码问题 [转自IBM]中文编码问题 JDBC入门 Jdbc事务控制管理 常用数据库连接池 编写JDBC框架 客户信息管理系统 Servlet Filter 过滤器 HTTP 协议 文件上传和下载 Servlet事件监听器 JavaMail开发 ...

    JavaWeb开发中文乱码问题解决方案

    中文乱码问题是JavaWeb开发中最常见的问题之一,解决的方法也有很多种,其中,过滤器是最常用的方法之一。提供了过滤器的源码和详细配置。

    Spring的学习笔记

    第一课:面向抽象编程 4 第二课:Jdom的基本使用 4 第三课:模拟Spring功能 5 第四课:搭建sping的运行...三、 中文乱码问题: 44 第十三课:SSH整合的jar包 45 一、 Struts2 45 二、 Hibernate3.3.2 45 三、 Spring 46

    ASN.1中文学习笔记

    ASN.1是ITU-T的一个标准集,它用来编码及表示通用数据类型,这些数据类型有可打印串值,八位位组串值,位串值,整数值以及用可移值方式组合而成 的其他类型序列值.简单的说,ASN.1指定了以何种方式对非平凡的数据...

    Qt工作笔记-Qt5中中文编码方面的笔记

    如果没有指定本地字符集,在qtcreator上开发或者其他Qt项目上,使用的是UTF-8编码,就算去toStdString()也是to到了UTF-8编码。 使用这个函数去设置项目的字符集: QTextCode::setCodecForLocale(QTextCodec::...

    struts2学习笔记!

    struts2学习笔记!因为还没有全部学完,所以分部分分享!主要内容:struts.xml配置,web.xml配置 Action要点!...类型装换错误的处理问题局部使用,把中文汉字转换为编码 struts2对数据转换与输入校验流程

    SIM800C使用PDU模式发送短信实践笔记.txt

    针对SIM800C通讯模块,如何向10086号码发短信,及PDU编码的详细规则进行了梳理,形成该学习实践笔记。

    Struts1.3 备忘笔记

    06 Struts_06Filter : 中文编码的统一处理,通过Struct的请求处理器接口RequestProcessor(中央控制器)来实现 07 Struts_07ForwardAction : 访问WebRoot/WEB-INF/下文件的一种方式 08 Struts_08DynaValidatorForm : ...

    解决vs 2010复制汉字到Word出现乱码总结

    为了解决vs2010复制汉字到Word出现乱码的问题,采用两种方式进行,第一种是使用工具,是临时性的。第二种是要安装sp1可以修复该bug,是永久性的。

    IBM WebSphere Portal门户开发笔记01

    2、 火狐浏览器设置为中文 367 3、 使新配置的域名生效 367 十九、PORTAL相关 368 1、完整主机名设置 368 2、向SWF图片新闻播放器添加带有&符号的多个参数 368 3、SCHEME模式文件代码 369 4、ECLIPSE添加SVN 370 5、...

    PYTHON自然语言处理(中文版)笔记1

    2、自然语言处理 1、单语料库使用 2、使用自己的预料库 3、生成随机文本 4、条件概率 5、词典语料 1、从网络和硬盘访问文本 2、编码 3、正则表达式 4、

    学习笔记.docx

    java笔记...........................................................................................1. 程序员职业发展: 1.一线程序员 2.一直走技术 3.管理层 4.泛IT、讲师、运维、项目经理和产品经理 5.自己...

    spring2.5 学习笔记

    第一课:面向抽象编程 4 第二课:Jdom的基本使用 4 第三课:模拟Spring功能 5 第四课:搭建sping的运行...三、 中文乱码问题: 44 第十三课:SSH整合的jar包 45 一、 Struts2 45 二、 Hibernate3.3.2 45 三、 Spring 46

    Struts2 学习笔记

    十、 Action属性接收参数中文问题 12 十一、 简单数据验证 12 十二、 访问Web元素 14 一、 方法一:ActionContext方式 15 二、 方式二:Ioc(控制反转)—推荐使用 15 三、 方式三:获取原类型 16 四、 方式四:获取原...

Global site tag (gtag.js) - Google Analytics