小师妹学JavaIO之:文件编码和字符集Unicode
简介
小师妹一时兴起,使用了一项从来都没用过的新技能,没想却出现了一个无法解决的问题。把大象装进冰箱到底有几步?乱码的问题又是怎么解决的?快来跟F师兄一起看看吧。
更多精彩内容且看:
- 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
- Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
- Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
- java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
使用Properties读取文件
这天,小师妹心情很愉悦,吹着口哨唱着歌,标准的45度俯视让人好不自在。
小师妹呀,什么事情这么高兴,说出来让师兄也沾点喜庆?
小师妹:F师兄,最新我发现了一种新型的读取文件的方法,很好用的,就跟map一样:
public void usePropertiesFile() throws IOException {
Properties configProp = new Properties();
InputStream in = this.getClass().getClassLoader().getResourceAsStream("www.flydean.com.properties");
configProp.load(in);
log.info(configProp.getProperty("name"));
configProp.setProperty("name", "www.flydean.com");
log.info(configProp.getProperty("name"));
}
F师兄你看,我使用了Properties来读取文件,文件里面的内容是key=value形式的,在做配置文件使用的时候非常恰当。我是从Spring项目中的properties配置文件中得到的灵感,才发现原来java还有一个专门读取属性文件的类Properties。
小师妹现在都会抢答了,果然青出于蓝。
乱码初现
小师妹你做得非常好,就这样触类旁通,很快java就要尽归你手了,后面的什么scala,go,JS等估计也统统不在话下。再过几年你就可以升任架构师,公司技术在你的带领之下一定会蒸蒸日上。
做为师兄,最大的责任就是给小师妹以鼓励和信心,给她描绘美好的未来,什么出任CEO,赢取高富帅等全都不在话下。听说有个专业的词汇来描述这个过程叫做:画饼。
小师妹有点心虚:可是F师兄,我还有点小小的问题没有解决,有点中文的小小乱码....
我深有体会的点点头:马赛克是阻碍人类进步的绊脚石...哦,不是马赛克,是文件乱码,要想弄清楚这个问题,还要从那个字符集和文件编码讲起。
字符集和文件编码
在很久很久以前,师兄我都还没有出生的时候,西方世界出现了一种叫做计算机的高科技产品。
初代计算机只能做些简单的算数运算,还要使用人工打孔的程序才能运行,不过随着时间的推移,计算机的体积越来越小,计算能力越来越强,打孔已经不存在了,编程了人工编写的计算机语言。
一切都在变化,唯有一件事情没有变化。这件事件就是计算机和编程语言只流传在西方。而西方日常交流使用26个字母加有限的标点符号就够了。
最初的计算机存储可以是非常昂贵的,我们用一个字节也就是8bit来存储所有能够用到的字符,除了最开始的1bit不用以外,总共有128中选择,装26个小写+26个大写字母和其他的一些标点符号之类的完全够用了。
这就是最初的ASCII编码,也叫做美国信息交换标准代码(American Standard Code for Information Interchange)。
后面计算机传到了全球,人们才发现好像之前的ASCII编码不够用了,比如中文中常用的汉字就有4千多个,怎么办呢?
没关系,将ASCII编码本地化,叫做ANSI编码。1个字节不够用就用2个字节嘛,路是人走出来的,编码也是为人来服务的。于是产生了各种如GB2312, BIG5, JIS等各自的编码标准。这些编码虽然与ASCII编码但是相互之间缺并不兼容。
这严重的影响了国际化的进程,这样还怎么去实现同一个地球,同一片家园的梦想?
于是国际组织出手了,制定了UNICODE字符集,为所有语言的所有字符都定义了一个唯一的编码,unicode的字符集是从U+0000到U+10FFFF这么多个编码。
小师妹:F师兄,那么unicode和我平时听说的UTF-8,UTF-16,UTF-32有什么关系呢?
我笑着问小师妹:小师妹,把大象装进冰箱有几步?
小师妹:F师兄,脑筋急转弯的故事,已经不适合我了,大象装进冰箱有三步,第一打开冰箱,第二把大象装进去,第三关上冰箱,完事了。
小师妹呀,作为一个有文化的中国人,要真正的承担起民族复兴,科技进步的大任,你的想法是很错误的,不能光想口号,要有实际的可操作性的方案才行,要不然我们什么时候才能够打造秦芯,唐芯和明芯呢?
师兄说的对,可是这跟unicode有什么关系呢?
unicode字符集最后是要存储到文件或者内存里面的,那怎么存呢?使用固定的1个字节,2个字节还是用边长的字节呢?根据编码方式的不同,可以分为UTF-8,UTF-16,UTF-32等多种编码方式。
其中UTF-8是一种变长的编码方案,它使用1-6个字节来存储。UTF-16使用2个或者4个字节来存储,JDK9之后的String的底层编码方式变成了两种:LATIN1和UTF16。
而UTF-32是使用4个字节来存储。这三种编码方式中,只有UTF-8是兼容ASCII的,这也是为什么国际上UTF-8编码方式比较通用的原因(毕竟计算机技术都是西方人搞出来的)。
解决Properties中的乱码
小师妹,要解决你Properties中的乱码问题很简单,Reader基本上都有一个Charsets的参数,通过这个参数可以传入要读取的编码方式,我们把UTF-8传进去就行了:
public void usePropertiesWithUTF8() throws IOException{
Properties configProp = new Properties();
InputStream in = this.getClass().getClassLoader().getResourceAsStream("www.flydean.com.properties");
InputStreamReader inputStreamReader= new InputStreamReader(in, StandardCharsets.UTF_8);
configProp.load(inputStreamReader);
log.info(configProp.getProperty("name"));
configProp.setProperty("name", "www.flydean.com");
log.info(configProp.getProperty("name"));
}
上面的代码中,我们使用InputStreamReader封装了InputStream,最终解决了中文乱码的问题。
真.终极解决办法
小师妹又有问题了:F师兄,这样做是因为我们知道文件的编码方式是UTF-8,如果不知道该怎么办呢?是选UTF-8,UTF-16还是UTF-32呢?
小师妹问的问题越来越***钻了,还好这个问题我也有准备。
接下来介绍我们的终极解决办法,我们将各种编码的字符最后都转换成unicode字符集存到properties文件中,再读取的时候是不是就没有编码的问题了?
转换需要用到JDK自带的工具:
native2ascii -encoding utf-8 file/src/main/resources/www.flydean.com.properties.utf8 file/src/main/resources/www.flydean.com.properties.cn
上面的命令将utf-8的编码转成了unicode。
转换前:
site=www.flydean.com
name=程序那些事
转换后:
site=www.flydean.com
name=\u7a0b\u5e8f\u90a3\u4e9b\u4e8b
再运行下测试代码:
public void usePropertiesFileWithTransfer() throws IOException {
Properties configProp = new Properties();
InputStream in = this.getClass().getClassLoader().getResourceAsStream("www.flydean.com.properties.cn");
configProp.load(in);
log.info(configProp.getProperty("name"));
configProp.setProperty("name", "www.flydean.com");
log.info(configProp.getProperty("name"));
}
输出正确的结果。
如果要做国际化支持,也是这样做的。
总结
千辛万苦终于解决了小师妹的问题,F师兄要休息一下。
本文的例子https://github.com/ddean2009/learn-java-io-nio
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/io-charsets-properties/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
小师妹学JavaIO之:文件编码和字符集Unicode的更多相关文章
- 小师妹学JavaIO之:文件系统和WatchService
目录 简介 监控的痛点 WatchService和文件系统 WatchSerice的使用和实现本质 总结 简介 小师妹这次遇到了监控文件变化的问题,F师兄给小师妹介绍了JDK7 nio中引入的Watc ...
- 小师妹学JavaIO之:文件File和路径Path
简介 文件和路径有什么关系?文件和路径又隐藏了什么秘密?在文件系统的管理下,创建路径的方式又有哪些?今天F师兄带小师妹再给大家来一场精彩的表演. 文件和路径 小师妹:F师兄我有一个问题,java中的文 ...
- 小师妹学JavaIO之:MappedByteBuffer多大的文件我都装得下
目录 简介 虚拟地址空间 详解MappedByteBuffer MapMode MappedByteBuffer的最大值 MappedByteBuffer的使用 MappedByteBuffer要注意 ...
- 小师妹学JavaIO之:目录还是文件
目录 简介 linux中的文件和目录 目录的基本操作 目录的进阶操作 目录的腰疼操作 总结 简介 目录和文件傻傻分不清楚,目录和文件的本质到底是什么?在java中怎么操纵目录,怎么遍历目录.本文F师兄 ...
- 小师妹学JavaIO之:用Selector来发好人卡
目录 简介 Selector介绍 创建Selector 注册Selector到Channel中 SelectionKey selector 和 SelectionKey 总的例子 总结 简介 NIO有 ...
- 小师妹学JavaIO之:NIO中Channel的妙用
目录 简介 Channel的分类 FileChannel Selector和Channel DatagramChannel SocketChannel ServerSocketChannel Asyn ...
- 小师妹学JavaIO之:Buffer和Buff
目录 简介 Buffer是什么 Buffer进阶 创建Buffer Direct VS non-Direct Buffer的日常操作 向Buffer写数据 从Buffer读数据 rewind Buff ...
- 小师妹学JavaIO之:NIO中那些奇怪的Buffer
目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,Buf ...
- 小师妹学IO系列文章集合-附PDF下载
目录 第一章 IO的本质 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 第二章 try with和它的底层原理 简介 IO关闭的问题 使用try with resource ...
- 小师妹学JVM之:JVM的架构和执行过程
目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...
随机推荐
- 格式化占位符%r和!r
# 作用 都是格式化原形输出,!r用于format格式化,%r用于%格式化 # 示例 a = '123' b = 'hello, {!r}'.format(a) b = 'hello, %r' % ( ...
- centos8.x阿里源配置
>>> cd /etc/yum.repo.d >>> mkdir bak >>> mv *.repo bak/ >>> cd b ...
- Kotlin 协程二 —— 通道 Channel
目录 一. Channel 基本使用 1.1 Channel 的概念 1.2 Channel 的简单使用 1.3 Channel 的迭代 1.4 close 关闭 Channel 1.5 Channe ...
- 【C++ OOP 02 对象的初始化和清理】构造/析构函数、深/浅拷贝、初始化列表以及静态成员
[对象的初始化和清理] 生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全 C++中的面向对象来源于生活,每个对象也都会有初始设置以及 对象销毁前的清理数据 ...
- 【LeetCode数组#2双指针法】移除元素、删除有序数组中的重复项、移动0
移除元素 力扣27题目链接(opens new window) 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用额外的数组 ...
- 【Azure API 管理】APIM添加Log-to-eventhub的策略后,一些相关APIM与Event Hub的问题
问题描述 1) APIM 到Event Hub 写入日志是否有数量限制,比如每秒最大写入数量: 2) 是否可以在同一个APIM配置多个Event Hub,如果可以该APIM写入日志的峰值是 ...
- ffmpeg 使用记录
这周周末尝试把我硬盘上面的视频文件压缩了一下,但是效果并不理想.其中主要有两个原因, 视频本来就是h264的编码,再重新编码也没啥用,因为限制大小的主要是码率 ffmpeg GPU加速版的h265编码 ...
- 【规范】Apifox就应该这么玩
前言 缘由 好的工具就要配好的玩法 起因是最近在回顾项目时,看到了年事已高并且长时间不用的Postman,发现之前自己整理的接口文档十分混乱且没有规律.遂打开现在使用的Apifox,将本狗目前项目中使 ...
- Linux 系统错误码 errno 剖析
一.errno 介绍 1.1 errno 简介 Linux 中系统调用的错误都存储于错误码 errno 中.errno 由操作系统维护,存储就近发生的错误,即下一次的错误码会覆盖掉上一次的错误. er ...
- 【Azure Power BI】Power BI获取SharePoint List列表后,如何展开List/Table中的字段,以及使用逗号拼接为一个字符串
问题描述 Power BI获取SharePoint List列表作为数据源.但是在数据源中,有Table属性值,有List属性值.如果直接展开,则会形成"笛卡尔"集的效果,变成N多 ...