Java使用csv导出大批量数据(一)

话不多说,此处分享一下整个过程:

1.选取合适的第三方类库,有Apache的,有javacsv的,最终选择了Apache的,因为功能比较多(但是我两个都试过,导出的速度两者相差不大,Javacsv会稍快一些,追求极限速度可以选用)。

2.老样子,maven仓库找到依赖,导入项目pom文件。 

这是javacsv的引入:

<dependency>
    <groupId>net.sourceforge.javacsv</groupId>
    <artifactId>javacsv</artifactId>
    <version>2.0</version>
</dependency>

这是Apache的引入:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.9.0</version>
</dependency>

3.编写导出逻辑代码,代码也相对简单,因为没有Excel那样,可以设置各种样式,格式,csv就是纯逗号分隔。当然,如果需要用Excel打开,这里面还是要有点坑的,下面会细说,直接贴代码

这是Javacsv的:

public static void writeFile(String filePath, Charset charset) {

        CsvWriter csvWriter = new CsvWriter(filePath, ',', charset);

        try {
            // 定义 header 头
            String[] headers = {"订单号", "用户名", "支付金额"};
            // 写入 header 头
            csvWriter.writeRecord(headers);

            // 写入一万条记录
            for (int i = 0; i < 10000; i++) {
                String orderNum = UUID.randomUUID().toString();
                String userName = "用户" + i;
                String payMoney = String.valueOf(i);

                // 写入行
                csvWriter.writeRecord((String[]) Arrays.asList(orderNum, userName, payMoney).toArray());
            }
        } catch (Exception e) {
            log.error("writeFile err-", e);
        } finally {
            csvWriter.close();
        }
    }

这是Apache的:

public static void writeFile1(String filePath, Charset charset) {

        try (CSVPrinter csvPrinter = new CSVPrinter(new OutputStreamWriter(new FileOutputStream(filePath), charset), CSVFormat.EXCEL)) {

            //列头
            csvPrinter.printRecord("订单号", "用户名", "支付金额");

            for (int i = 0; i < 10000; i++) {
                String orderNum = "\t0032daawe10202111259dd95dd542060d207dd17678" + i;
                String userName = "\t用户" + i;
                String payMoney = String.valueOf(i);

                csvPrinter.printRecord(Arrays.asList(orderNum, userName, payMoney));
            }
            csvPrinter.close(true);
        } catch (IOException e) {
            log.error("writeFile1 err-", e);
        } 
    }

细心的小伙伴会发现,用Apache的这份在订单号的值前面加了一个制表符,此处就是第一个坑。因为你导出之后用office 的Excel软件打开后会发现数字类型的值超长的话会被转换成科学计数法的形式呈现,所以此处加了制表符就可以避免这种情况出现(当前你可以可以尝试其他符号,但是制表符会让数据看上去没任何变化)。

好了,导出就是这样,是不是很简单呢?(由于篇幅问题,下一篇有我的整合版,感兴趣的小伙伴可以前去看看)

到处为止就结束了吗?不,还没有,还有一个坑,下面继续讲讲:

可能很多小伙伴都会遇到导出后用Excel打开会出现中文乱码问题,但是如果用文件编辑器、记事本之类的打开显示内容是正常的,这里就是另外一个坑了:

原因:

编码不统一,用office的Excel打开的CSV文件默认是ANSI编码,因为我们导出时设置的编码一般都是UTF-8或者GBK等编码,这样可能就会出现文件乱码的情况,因为记事本、文件编辑器等工具支持UTF-8编码,所以用记事本、文件编辑器打开显示正常。

解决办法:

就是告诉Excel用UTF-8打开,怎么告诉,通过添加BOM标识,这里是搜索了相关资料发现的,感兴趣的小伙伴可以看到最后,小编会说明情况。

byte[] uft8bom = {(byte) 0xEF, (byte) 0xBB,(byte) 0xBF};//先写入BOM,防止生成的csv用Excel打开乱码
FileOutputStream outputStream = new FileOutputStream(filePath);
outputStream.write(uft8bom);

扩展说明

BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode编码标准中用于标识文件是采用哪种格式的编码。Windows就是使用BOM来标记文本文件的编码方式的。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。当文本程序读取到以EF BB BF开头的字节流时,就知道这是UTF-8编码了。同理,若没有BOM的场合,可能无法正确识别编码,工具会使用默认的编码,编码不匹配则会导致乱码

UTF-8文件中包含BOM的坏处
对php的影响
PHP并不会忽略BOM,所以在读取、包含或者引用这些文件时,会把BOM作为该文件开头正文的一部分。根据嵌入式语言的特点,这串字符将被直接执行(显示)出来。由此造成即使页面的 top padding 设置为0,也无法让整个网页紧贴浏览器顶部,因为在html一开头有这3个字符呢!

                                                                                                                        -----------来源百度百科


版权声明:本文为u012733059原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。