zoukankan      html  css  js  c++  java
  • 解决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纯属是微软的习惯。

    说了这么多,你是不是有点迷糊呢?其实,我也迷糊,所以我要继续去补知识了,拜~

  • 相关阅读:
    C# 对Outlook2010进行二次开发
    利用AForge.NET 调用电脑摄像头进行拍照
    SQL2012 提示评估已过期 解决方案- sql server问题
    图片转换PDF
    [转载]理解weight decay
    ATTENTION NETWORK分析
    sys.stdout.write和print和sys.stdout.flush
    Flutter免费(视频)教程汇总
    Windows核心编程随笔
    .NET家族
  • 原文地址:https://www.cnblogs.com/edda/p/12795535.html
Copyright © 2011-2022 走看看