Java中常见的编码集问题
收录于热门专栏Java基础教程系列(进阶篇)
一、遇到一个问题
1、读取CSV文件
package com.guor.demo.charset;import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class CommonUtils {public static List<Map<String, Object>> readCSVToList(String filePath) throws Exception {List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();BufferedReader reader = null;try {reader = new BufferedReader(new FileReader(filePath));String[] headtilte = reader.readLine().split(",");String line = null;while ((line = reader.readLine()) != null) {HashMap<String, Object> hashMap = new HashMap<String, Object>();String[] itemArray = line.split(",");for (int i = 0; i < itemArray.length; i++) {hashMap.put(headtilte[i], itemArray[i]);}list.add(hashMap);}} catch (Exception e) {e.printStackTrace();} finally {if (null != reader) {reader.close();}}return list;}public static void main(String[] args) throws Exception {String filePath = "H:\\CSDN\\netty\\编码集问题\\test.csv";System.out.println(readCSVToList(filePath));}
}
2、控制台输出
这是什么鬼?
原来我的csv文件的编码集是带BOM的UTF-8,没听过啊,众里寻他千百度。
二、带有BOM的UTF-8
1、BOM
在UCS 编码中有一个叫做 “Zero Width No-Break Space” ,中文译名作“零宽无间断间隔”的字符,它的编码是 FEFF。而 FEFF 在 UCS 中是不存在的字符,所以不应该出现在实际传输中。UCS 规范建议我们在传输字节流前,先传输字符 “Zero Width No-Break Space”。这样如果接收者收到 FEFF,就表明这个字节流是 Big-Endian 的;如果收到FFFE,就表明这个字节流是 Little- Endian 的。因此字符 “Zero Width No-Break Space” (“零宽无间断间隔”)又被称作 BOM。
2、UTF-8
UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是针对Unicode的一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部分修改后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。
3、UTF-8 BOM
UTF-8 不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。字符 “Zero Width No-Break Space” 的 UTF-8 编码是 EF BB BF。所以如果接收者收到以 EF BB BF 开头的字节流,就知道这是 UTF-8编码了。Windows 就是使用 BOM 来标记文本文件的编码方式的。
4、CSV文件乱码问题
类似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入UTF-8 BOM头。记事本等编辑器通过它来识别这个文件是否以UTF-8编码(当然即便没有UTF-8 BOM头记事本也能通过其它方式正确识别UTF-8编码)。
三、编码解码
在计算机发展初期,美国等少数国家最先给自己的语言设置了一套编码,即ASCII。因为英语只有26个英文字母及一些常见的符号即可,因此只需要一个字节的 7 位(即 128 个整数)就能完全表示英文字符。
但随着计算机的发展,欧洲一些国家也需要为自己的语言设置一套编码,ASCII的128个字符不够用了,因此就产生了第二套编码类型 ISO-8859-1 ~ ISO-8859-15,其中使用最广泛的是ISO-8859-1,ISO-8859-1使用了一个字节的 8 位,可以表示256个字符。为了避免乱码问题,ISO-8859-1完全兼容ASCII,ISO-8859-1的前128位和ASCII完全一致,后128个字符才是ISO-8859-1自身新扩展的字符编码。
后来,中国也给汉语设置了一套编码,提出了适合汉语的编码集GB2312。GB2312包含了682个英文、字母等符号及常见的6763个简体中文,我勒个去,中华上下五千年,博大精深啊。
再后来,为了将简体中文和繁体中文兼容到字符集里,又发布了新的编码集GBK。GBK实际是GB2312的扩展,使用1个字节存储ASCII中的字符,使用2个字节存储一个中文汉字。
最后,为了给世界上的所有字符设置一套统一的编码集,出台了统一的字符集规范Unicode(国际标准字符集)。其中就包含最著名的UTF-8。
UTF-8是ASCII的超集,ASCII中每个字符的编码与UTF-8是完全一致的,因此当用UTF-8存储汉字或其他字符时,可能会使用2个、3个或4个字节。
- 1个字节:英文,数字,回车符,ASCII中的常用符号+、-、*、/等;
- 2个字节:个别特殊符号;
- 3个字节:常见汉字,在GBK中存在的汉字;
- 4个字节:中日韩等超大字符集里面的汉字;
在java.nio.charset.Charset类中,提供了一些编码及常用方法。
四、解决读取“带有BOM的UTF-8文件乱码”问题
1、读取文件编码集
按照给定的字符集存储文件时,在文件的最开头的三个字节中就有可能存储着编码信息,所以,基本的原理就是只要读出文件前三个字节,判定这些字节的值,就可以得知其编码的格式。其实,如果项目运行的平台就是中文操作系统,如果这些文本文件在项目内产生,即开发人员可以控制文本的编码格式。
2、用指定的编码格式读取文件流,写入文件流
(1)读取CSV文件
public static List<String[]> readCSVToListByUnicode(String filePath) {FileInputStream fis = null;UnicodeInputStream uin = null;InputStreamReader in= null;try {//logger.info("读取文件"+filePath+"编码集");List<String[]> list = new ArrayList<String[]>();//URL url = new URL(filePath);File f = new File(filePath);fis = new FileInputStream(f);uin = new UnicodeInputStream(fis,enc); //如果是本地将url.openStream -> new FileInputStream(f)enc = uin.getEncoding(); // check and skip possible BOM bytesif (enc == null){in = new InputStreamReader(uin);}else {in = new InputStreamReader(uin, enc);}long start = System.currentTimeMillis();//logger.info("读取文件"+filePath+"查看耗时开始");BufferedReader reader = new BufferedReader(in);//BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("D:/tags.txt"),"utf-8"));//String tmp =reader.readLine();String[] headtilte = reader.readLine().split(",");list.add(headtilte);String line = null;String[] itemArray = null;while ((line = reader.readLine()) != null) {itemArray = line.split(",");list.add(itemArray);}long end = System.currentTimeMillis();//logger.info("读取文件"+filePath+"查看耗时="+(end-start)+"毫秒");return list;}catch (Exception e){logger.info("读取文件"+filePath+",异常:", e);return null;}finally {try {if(in!=null){in.close();}if(uin!=null){uin.close();}if(fis!=null){fis.close();}}catch (Exception e){logger.info("读取文件"+filePath+",关闭流异常:", e);}}}
(2)获取文件编码集
package com.guor.demo.utils;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;public class UnicodeInputStream extends InputStream {private static final Logger logger = LoggerFactory.getLogger(UnicodeInputStream.class);PushbackInputStream internalIn;boolean isInited = false;String defaultEnc;String encoding;private static final int BOM_SIZE = 4;public UnicodeInputStream(InputStream in, String defaultEnc) {internalIn = new PushbackInputStream(in, BOM_SIZE);this.defaultEnc = defaultEnc;}public String getDefaultEncoding() {return defaultEnc;}public String getEncoding() {if (!isInited) {try {init();} catch (IOException ex) {IllegalStateException ise = new IllegalStateException("Init method failed.");ise.initCause(ise);throw ise;}}return encoding;}/*** Read-ahead four bytes and check for BOM marks. Extra bytes are* unread back to the stream, only BOM bytes are skipped.*/protected void init() throws IOException {if (isInited) {return;}byte bom[] = new byte[BOM_SIZE];int n, unread;n = internalIn.read(bom, 0, bom.length);//logger.info("文件的前四个字符==="+bom[0]+","+bom[1]+","+bom[2]+","+bom[3]);if ( (bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) &&(bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF) ) {encoding = "UTF-32BE";unread = n - 4;} else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) &&(bom[2] == (byte)0x00) && (bom[3] == (byte)0x00) ) {encoding = "UTF-32LE";unread = n - 4;} else if ( (bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) &&(bom[2] == (byte)0xBF) ) {encoding = "UTF-8";unread = n - 3;} else if ( (bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF) ) {encoding = "UTF-16BE";unread = n - 2;} else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) ) {encoding = "UTF-16LE";unread = n - 2;} else {// Unicode BOM mark not found, unread all bytesencoding = defaultEnc;unread = n;}//System.out.println("read=" + n + ", unread=" + unread);if (unread > 0) {internalIn.unread(bom, (n - unread), unread);}isInited = true;}@Overridepublic void close() throws IOException {//init();isInited = true;internalIn.close();}@Overridepublic int read() throws IOException {//init();isInited = true;return internalIn.read();}
}
收录于热门专栏Java基础教程系列(进阶篇)
Java学习路线总结,搬砖工逆袭Java架构师
10万字208道Java经典面试题总结(附答案)
Java基础教程系列
Java基础教程系列(进阶篇)
相关文章:
Java中常见的编码集问题
收录于热门专栏Java基础教程系列(进阶篇) 一、遇到一个问题 1、读取CSV文件 package com.guor.demo.charset;import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.L…...
数据结构与算法(Java版) | 就让我们来看看几个实际编程中遇到的问题吧!
上一讲,我给大家简单介绍了一下数据结构,以及数据结构与算法之间的关系,照理来说,接下来我就应该要给大家详细介绍线性结构和非线性结构了,但是在此之前,我决定还是先带着大家看几个实际编程中遇到的问题&a…...
【C++算法】dfs深度优先搜索(上) ——【全面深度剖析+经典例题展示】
💃🏼 本人简介:男 👶🏼 年龄:18 📕 ps:七八天没更新了欸,这几天刚搞完元宇宙,上午一直练🚗,下午背四级单词和刷题来着,还在忙一些学弟…...
总结高频率Vue面试题
目录 什么是三次握手? 什么是四次挥手?(close触发) 什么是VUEX? 什么是同源----跨域? 什么是Promise? 什么是fexl布局? 数据类型 什么是深浅拷贝? 什么是懒加载&…...
IP协议详解
目录 前言: IP协议 提出问题 解决方案 地址管理 子网掩码 路由选择 小结: 前言: IP协议作为网络层知名协议。当数据经过传输层使用TCP或者UDP对数据进行封装,然后当数据到达网络层,基于TCP或UDP数据包继续进行…...
webpack5 基础配置
在开发中,我们会使用 vue、react、less、scss等语法进行开发项目,但是浏览器只能识别 js、css,或者说在js中使用了es6中的import 导入 这时候也需要打包工具去转换成浏览器可以识别的语句。 一、使用webpack 1.初始化package.json npm i…...
IDEA入门安装使用教程
一、背景 作为一个Java开发者,有非常多编辑工具供我们选择,比如Eclipse、IntelliJ IDEA、NetBeans、Visual Studio Code、Sublime Text等等,这些有免费也有收费的,但是就目前市场占比来说普遍使用Eclipse和IntelliJ IDEA这两款主…...
Lambda表达式使用及详解
一 Lambda表达式的简介 Lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。 Lambda表达式的使用场景:用以简…...
JAVA练习52-打家劫舍
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目-打家劫舍 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 2月16日练习内容 提…...
简单谈一谈幂等测试
1、什么是幂等测试 幂等是一个抽象的概念,在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同,即多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。幂等测试,则主…...
typescript复习笔记
数组类型-限定每一项的类型 //写法一 const arrNumber: number[] [1, 2, 3] const arrString: string[] [a, b, c] //写法二 const arrNumber2: Array<number> [1, 2, 3] const arrString2: Array<string> [a, b, c]联合类型 符号是 | //数组可以存放字符串或…...
webstorm开发electron,调试主进程方案
官网教程地址:https://www.electronjs.org/zh/docs/latest/tutorial/debugging-main-process 我只能说官网太看得起人了,整这么简易的教程…… 命令行开关 第一步还是要按要求在我们的package.json里加上端口监听:–inspect5858 我的命令…...
2W字正则表达式基础知识总结,这一篇就够了!!(含前端常用案例,建议收藏)
正则表达式 (Regular Expression,简称 RE 或 regexp ) 是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")正则表达式使用单个字符串来描述、匹配一系列匹…...
自学web前端觉得好难,可能你遇到了这些困境
好多人跟我说上学的时候也学过前端,毕业了想从事web前端开发的工作,但自学起来好难,快要放弃了,所以我总结了一些大家遇到的困境,希望对你会有所帮助。 目录 1. 意志是否坚定 2. 没有找到合适自己的老师 3. 为了找…...
ASEMI中低压MOS管18N20参数,18N20封装,18N20尺寸
编辑-Z ASEMI中低压MOS管18N20参数: 型号:18N20 漏极-源极电压(VDS):200V 栅源电压(VGS):30V 漏极电流(ID):18A 功耗(PD&#x…...
[NetBackup]客户端安装后server无法连通client
client name处填写客户端主机名,server to use for backups and restores处填写server端名字,与hosts文件内保持一致;source client for restores处填写client主机名,与server端hosts文件中保持一致,与主机实际名称保持…...
黑马Java后端项目实战--在线聊天交友
【课程简介】 越来越多的系统都有消息推送的功能,如聊天室、邮件推送、系统消息推送等; 要实现消息推送就需要服务端在数据有变化时主动推送消息给客户端,本次课程将带大家使用websocket实现消息推送。 【主讲内容】 1.方法:如…...
【实战系列 2】Yapi接口管理平台Getshell-Linux后门权限维持与痕迹清除
文章目录 前言一、网站主页到Getshell二、SSH软链接后门三、Linux权限维持 --隐藏踪迹3.1 隐藏远程SSH登陆记录3.2、ssh软链接后门连接失败的原因以及解决办法3.3、隐藏踪迹-痕迹清楚3.3.1、隐藏历史操作命令3.3.2、隐藏文件/文件夹3.3.3、修改文件时间戳3.3.4、隐藏权限3.3.5、…...
设计模式之抽象工厂模式(C++)
作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 一、抽象工厂模式是什么? 抽象工厂模式是一种创建型的软件设计模式,该模式相当于升级版的工厂模式。 如果…...
Kotlin新手教程一(Kotlin简介及环境搭建)
目录一、 什么是Kotlin?二、为什么要使用Kotlin?三、使用IntelliJ IDEA搭建Kotlin四、Kotlin使用命令行编译一、 什么是Kotlin? Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,它也可以被编译成为 JavaScript 源代码&…...
【虚拟仿真】Unity3D打包WEBGL实现全屏切换
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 今天实现Unity3D打包WEBGL后实现按钮点击全屏和退出 全屏的实现…...
java对象内存结构分析与大小计算
java对象内存结构Java对象保存在堆中时,由三部分组成:对象头(object header):包括了关于堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。所有java对象都有一个共同的对象头格实例数据(Insta…...
RabbitMQ学习(七):交换器
〇、前言在之前的内容中,我们创建了一个工作队列。我们假设的是工作队列背后,每个任务都恰好交付给一个消 费者(工作进程)。在今天的内容中,我们将做一些完全不同的事情——我们将消息传达给多个消费者。这种模式 称为 “发布/订阅”。为了说…...
cmd命令大全
文章目录变量输入输出逻辑命令符控制语句函数注释变量 在批处理中,变量全部是弱类型的,通常可以当做字符串处理 1.初始化定义 set varthis a var 2.获取变量值 %var% 3.链接 set varcat%var1%%var2% 4.截取 %var:~n,m% n是起点,m是长度&…...
Git的使用方法(保姆级)
一、安装git二、创建凭据 ①打开电脑的凭据管理器git:https://gitee.com是固定写法用户名、密码是你创建gitee的用户名、密码三、在gitee中创建一个仓库四、项目提交到仓库的方法①选择一个项目交由git管理按照步骤一中召唤小黑窗口输入 git init 就可以出现.git文件夹②右键选…...
TypeScript 学习之泛型
泛型使用 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型。就需要使用泛型。使用泛型就不会丢失类型信息,使用any会丢失类型信息。 function identity<T>(arg: T): T {return arg; }identity 添加了类型变量T, T 捕获用户传入的类型…...
新手学习node.js基础,node.js安装过程,node.js运行环境及javascript运行环境.
学习node.js1.什么是node.js?2.node.js中的javaScript运行环境3.node.js可以做什么?4. node.js学习思路5.node.js环境的安装6.如何在node.js中执行JavaScript代码1.什么是node.js? node.js是一个基于Chrome v8 引擎的JavaScript运行环境(后端) node.js官网 &…...
Maven的安装步骤(保姆级安装教程)
一、安装本地Maven 选择你需要的maven版本下载:官网下载传送门 我使用的是3.6.1版本:maven-3.6.1-bin.zip 二、安装 把下载好的maven压缩包解压到一个没有中文,空格或其他特殊字符的文件夹,如: 三、配置环境变量…...
Axure教程(一)——线框图与高保真原型图制作
前面我们学习了制作网页的技能,从这里开始我们来学习前端必备技能,就是用Axure来制作原型图,一方面我们能提前绘制出我们所需的页面,这在我们开发的时候能节省大量的时间,另一方面我们能通过给用户进行体验从而能够发现…...
wholeaked:一款能够追责数据泄露的文件共享工具
关于wholeaked wholeaked是一款功能强大的文件共享工具,该工具基于go语言开发,可以帮助广大系统管理员和安全研究人员在组织发生数据泄露的时候,迅速找出数据泄露的“始作俑者”。 wholeaked可以获取被共享的文件信息以及接收人列表&#x…...
新势力网站建设/网站优化关键词排名
laravel-modules可以通过模块化的方式进行开发。 另外。我们开发可以不从app里面进行开发 因为app本身也携带了一些laravel的类。以后如果出来laravel 9 或者 laravel10的话 我们升级也好升级。因为我们已经新建了别的模块 效果如下 不需要手动 安装。 首先在 Laravel 项…...
自己建网站做推广/seo百度排名优化
原文自工程师Enmanuel Durn博客,传送门 最近(或者不是最近,这完全取决于您什么时候阅读这边文章),我正在跟我的团队伙伴讨论如何去处理这种需要根据不同的值去处理不同的情况的方法,通常对于这种情况下&…...
有哪些做司考真题的网站/今日国内新闻10则
基本介绍 开发者可以使用云开发快速开发小程序、小游戏、公众号网页等,并且原生打通微信开放能力。 发布小程序需要使用云开发。 开发者无需搭建服务器,可免鉴权直接使用平台提供的 API 进行业务开发。 配有云端数据库,与传统数据库相比操…...
建设电商网站/培训机构不退费最有效方式
linux shell命令下我们可以通过相关命令关闭和重启计算机,下面由学习啦小编为大家搜集整理了linux shell的关机命令是什么的相关知识,希望对大家有帮助!linux shell的关机命令问题描述对于Linux系统而言,许多时候是用于服务器之类的ÿ…...
一站式做网站开发/网推项目
一:什么是命令模式? 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。 请求以命令的形式包裹在对象中,并传给调用对象。 调用对象寻找可以处理该命令的合适的对象,并把该…...
wordpress与ftp/三台网站seo
原文:针对不同手机系统的LBS地图定位解决方案摘要: 针对目前的三种手机系统:Android安卓、S60塞班、IOS苹果,做出的三种不同的手机地图应用解决方案。 查阅了多数地图API对手机的支持情况,发现并没有一家能完全覆盖到这三个平台。…...