「问答」解决CSV文件用Excel打开乱码问题
这篇文章适合有一定编码基础的人看,纯手动解决乱码问题请参见:
转码保存后,重新打开即可。 转码操作如下: 编辑器->另存为->ASCII码格式文件/UTF-8含BOM格式->保存。
参考文章:https://blog.csdn.net/m0_37125796/article/details/73928157
我写了一个CSV文件的数据列表,用Excel打开之后发现全部乱码了,这让我很尴尬。
于是找到了上面这篇文章,参照他的方式,进行了一些修改,终于解决了这个问题。
解决办法:给CSV文件添加BOM头
什么是BOM?
简单来说,它是一个可以证明内容以什么编码格式存在的中间人。
Excel是ASCII码格式文件,而CSV文件是UTF-8格式。如果不进行兼容,这两种不同格式肯定没法正常展示的。
所以,我需要对UTF-8编码的CSV文件写入一个UTF-8的BOM头,告诉Excel“我是UTF-8编码的,你要按照我的编码格式来解析。”这样,Excel才能真正认清文件里的内容。
上面的参考文章给出的解决方案如下:
OutputStreamWriter osw = new OutputStreamWriter(resp.getOutputStream(), "UTF-8");
// 要输出的内容
result = (String)contentMap.get(RESPONSE_RESULT);
resp.setHeader("Content-Disposition", "attachment;filename=test.csv");
osw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB,(byte) 0xBF }));
osw.write(result);
osw.flush();
我兴高采烈地依葫芦画瓢,把我的代码成他那样,而且在我的mac电脑上已经运行成功了,Excel可以正常打开我的CSV文件。
于是,我兴高采烈地交货了,把我的成品发给了老大,让他检阅。
谁知,老大给我的答案是:“打开都是乱码。”
“怎么可能,我在我电脑上能打开啊!”我下意识地反驳了一句,后来想想好傻啊,难不成是老大骗我吗,还不赶紧去检查代码!
我带着疑问,老大也过来帮我看哪里出了问题,先上一段我修改前的代码:
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }));
osw.write(s);
osw.flush();
我按照参考的文章写了这代码,看起来好像没什么问题。但是老大看出了猫腻,他把文件以16进制格式打开,发现我的BOM头是EF BB 3F
,而我写入的BOM是EF BB BF
。为何有这样的差异,我的BF怎么变成3F了?
因为只有EF BB BF
才能表示UTF-8,所以差一个字母都不行。
老大怀疑问题出在osw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }));
上,String默认是UTF-16的编码,而我们写入时应该不带任何格式,才能让解析器读懂,如果被String这么一转,转成其他格式,这就不好说了。
不愧是老大,一语中的!
于是,我尝试把String去掉,直接写入byte数组的BOM。修改之后的代码如下:
FileOutputStream fos = new FileOutputStream(file);
fos.write(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF });
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.append(s);
osw.flush();
原来的osw.write()
也改成了osw.append()
。(这个不改也无碍)
最终运行结果是可喜的,可以成功打开。
其实我们两个电脑之间的差异,一个是windows,一个是mac。我怀疑是mac对BOM做了兼容,检查没有windows严格。后面我一查,其实UTF-8本身没有BOM,给它加上BOM纯属是微软的习惯。
说了这么多,你是不是有点迷糊呢?其实,我也迷糊,所以我要继续去补知识了,拜~
欢迎留言留下你的问题。
我是毛毛,感恩遇见你。
(2019-01-29 00:54)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解决keras使用cov1D函数的输入问题
- PHP PDOStatement::getColumnMeta讲解
- PHP PDOStatement::nextRowset讲解
- PHP _construct()函数讲解
- PHP PDOStatement::rowCount讲解
- Python 如何对文件目录操作
- Python字符串split及rsplit方法原理详解
- Laravel框架文件上传功能实现方法示例
- python中如何写类
- 什么是PHP7中的孤儿进程与僵尸进程
- Python爬虫小例子——爬取51job发布的工作职位
- 详解PHP素材图片上传、下载功能
- Python enumerate() 函数如何实现索引功能
- python打开文件的方式有哪些
- PHP实现二维数组按照指定的字段进行排序算法示例