Java 导出CSV文件

版权声明:本文为博主原创文章,欢迎大家转载,转载请注明出处: https://blog.csdn.net/Wjhsmart/article/details/88709914

一、前言

之前一直使用POI导出Excel文件,发现已经不满足需求了,后来了解CSV之后,发现速度快的飞起,决定把项目中的改成CSV的方式,这里记录下过程,把坑填一下,参考大佬文章:https://www.cnblogs.com/cjsblog/p/9260421.html。测试源码和jar都已经上传到了CSDN下载,有需要的同学,可以直接前往下:https://download.csdn.net/download/wjhsmart/11045070

二、准备工作

使用到的jar,maven代码,如果是使用jar,可以前往:https://mvnrepository.com 下载相应的jar

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

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.17</version>
    </dependency>

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.17</version>
    </dependency>


    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

三、测试代码

直接把下面代码复制到测试类中,对每个方法就可以运行

package com.junit.csv;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Before;
import org.junit.Test;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestCSV {
    /**
     * 测试输出到csv
     * @throws Exception
     */
    @Test
    public void testWrite() throws Exception {
        FileOutputStream fos = new FileOutputStream("/Users/weijinhui/Downloads/test.csv");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");

        CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader("姓名", "年龄", "家乡", "性别");
        CSVPrinter csvPrinter = new CSVPrinter(osw, csvFormat);

        // 第二种方式设置头部信息
//        csvPrinter = CSVFormat.DEFAULT.withHeader("姓名", "年龄", "家乡", "性别").print(osw);

        for (int i = 0; i < 10; i++) {
            csvPrinter.printRecord("张三", 20, "上海", "男");
        }
        csvPrinter.flush();
        csvPrinter.close();
    }

    /**
     * 测试读取
     * @throws IOException
     */
    @Test
    public void testRead() throws IOException {
        InputStream is = new FileInputStream("/Users/weijinhui/Downloads/test.csv");
        InputStreamReader isr = new InputStreamReader(is, "UTF8");
        Reader reader = new BufferedReader(isr);

        CSVParser parser = CSVFormat.EXCEL.withHeader("name", "age", "jia", "gender").parse(reader);
//        CSVParser csvParser = CSVParser.parse(reader, CSVFormat.DEFAULT.withHeader("name", "age", "jia"));
        List<CSVRecord> list = parser.getRecords();
        for (CSVRecord record : list) {
            System.out.println(record.getRecordNumber()
                    + ":" + record.get("name")
                    + ":" + record.get("age")
                    + ":" + record.get("jia")
                    + ":" + record.get("gender"));
        }

        parser.close();
    }

    /**
     * 分析Excel csv文件
     */
    @Test
    public void testParse() throws Exception {
        Reader reader = new FileReader("/Users/weijinhui/Downloads/test.csv");
        CSVParser parser = CSVFormat.EXCEL.parse(reader);
        for (CSVRecord record : parser.getRecords()) {
            System.out.println(record);
        }
        parser.close();
    }

    /**
     * 手动定义标题
     */
    @Test
    public void testParseWithHeader() throws Exception {
        Reader reader = new FileReader("/Users/weijinhui/Downloads/test.csv");
        CSVParser parser = CSVFormat.EXCEL.withHeader("id", "name", "code", "gender").parse(reader);
        for (CSVRecord record : parser.getRecords()) {
            System.out.println(record.get("id") + ","
                    + record.get("name") + ","
                    + record.get("code")
                    + record.get("gender"));
        }
        parser.close();
    }

    /**
     * 使用枚举定义头
     */
    enum MyHeaderEnum {
        ID, NAME, CODE, GENDER;
    }

    /**
     * 测试使用枚举定义头部
     * @throws Exception
     */
    @Test
    public void testParseWithEnum() throws Exception {
        Reader reader = new FileReader("/Users/weijinhui/Downloads/test.csv");
        CSVParser parser = CSVFormat.EXCEL.withHeader(MyHeaderEnum.class).parse(reader);
        for (CSVRecord record : parser.getRecords()) {
            System.out.println(record.get(MyHeaderEnum.ID) + ","
                    + record.get(MyHeaderEnum.NAME) + ","
                    + record.get(MyHeaderEnum.CODE) + ","
                    + record.get(MyHeaderEnum.GENDER));
        }
        parser.close();
    }


    private List<Map<String, String>> recordList = new ArrayList<>();

    /**
     * 初始化list
     */
    @Before
    public void init() {
        for (int i = 0; i < 5; i++) {
            Map<String, String> map = new HashMap<>();
            map.put("name", "zhangsan");
            map.put("code", "001");
            recordList.add(map);
        }
    }

    /**
     * 测试使用线程生成多个文件,模拟导出
     * @throws InterruptedException
     */
    @Test
    public void writeMuti() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CountDownLatch doneSignal = new CountDownLatch(2);

        executorService.submit(new exprotThread("/Users/weijinhui/Downloads/0.csv", recordList, doneSignal));
        executorService.submit(new exprotThread("/Users/weijinhui/Downloads/1.csv", recordList, doneSignal));

        doneSignal.await();
        System.out.println("Finish!!!");
    }

    /**
     * 定义导出线程
     */
    class exprotThread implements Runnable {

        private String filename;
        private List<Map<String, String>> list;
        private CountDownLatch countDownLatch;

        public exprotThread(String filename, List<Map<String, String>> list, CountDownLatch countDownLatch) {
            this.filename = filename;
            this.list = list;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                CSVPrinter printer = new CSVPrinter(new FileWriter(filename), CSVFormat.EXCEL.withHeader("NAME", "CODE"));
                for (Map<String, String> map : list) {
                    printer.printRecord(map.values());
                }
                printer.close();
                countDownLatch.countDown();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 测试写100万数据需要花费多长时间
     */
    @Test
    public void testMillion() throws Exception {
        int times = 10000 * 10;
        Object[] cells = {"满100减15元", "100011", 15};

        //  导出为CSV文件
        long t1 = System.currentTimeMillis();
        FileWriter writer = new FileWriter("/Users/weijinhui/Downloads/test1.csv");
        CSVPrinter printer = CSVFormat.EXCEL.print(writer);
        for (int i = 0; i < times; i++) {
            printer.printRecord(cells);
        }
        printer.flush();
        printer.close();
        long t2 = System.currentTimeMillis();
        System.out.println("CSV: " + (t2 - t1));

        //  导出为Excel文件
        long t3 = System.currentTimeMillis();
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet();
        for (int i = 0; i < times; i++) {
            XSSFRow row = sheet.createRow(i);
            for (int j = 0; j < cells.length; j++) {
                XSSFCell cell = row.createCell(j);
                cell.setCellValue(String.valueOf(cells[j]));
            }
        }
        FileOutputStream fos = new FileOutputStream("/Users/weijinhui/Downloads/test2.xlsx");
        workbook.write(fos);
        fos.flush();
        fos.close();
        long t4 = System.currentTimeMillis();
        System.out.println("Excel: " + (t4 - t3));
    }
}

附上测试 CSV 和 Excel 导出结果截图,会发现,CSV 何止是快的飞起,简直是快的不要不要的

四、遇到的坑

运行测试方法报下面的错误:java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing

java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:44)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.ClassNotFoundException: org.hamcrest.SelfDescribing
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 25 more

这是junit 4.1.1中没有hamcrest包了,如果遇到相同问题的同学,可以直接使用:http://central.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar,点击链接可以直接下载jar,引入项目即可。

展开阅读全文

没有更多推荐了,返回首页