Java 读写csv

本文结构:

  • 废话
  • 动手读csv
  • 写csv

工作中需要读写csv,由于csv 文件较大,数据比较多,所以需要选择一个速度快的csv 读取插件。经过比较选择opencsv 。官方解释:Opencsv是一个易于使用的CSV(逗号分隔值)解析器库。之所以开发它,是因为当时所有CSV解析器都没有商业友好的许可证。Java 7是目前支持的最小版本。

Opencsv

Opencsv支持您可能想要做的所有基本CSV类型的事情:

  • 每行的任意数量的值。

  • 忽略引用元素中的逗号。

  • 处理带有嵌入式回车的带引号的条目(即跨越多行的条目)。

  • 可配置的分隔符和引号字符(或使用合理的默认值)。

    所有这些事情都可以通过可塑性方法的表现来完成阅读和写作:

  • 往返于一个字符串数组。

  • 来自带注释的bean。

  • 来自数据库一次读取所有条目,或使用Iterator风格的模型

废话不多说:官方文档[http://opencsv.sourceforge.net/]

跟我一起做 读csv

引入依赖

<dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>4.2</version>
        </dependency>

读取csv 映射为对象(此时会按照csv 的顺序进行映射全量,如果需要只取csv中的部分列则看下一部分)

 public  static <T> List<T> getCsvData(Class<T> clazz) {
     
        InputStreamReader in=null;
        try {
     
            in = new InputStreamReader(new FileInputStream("xxxx.csv"), "gbk");
        } catch (Exception e) {
     

        }

        System.out.println(System.currentTimeMillis());
        HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
        strategy.setType(clazz);

        CsvToBean<T> csvToBean = new CsvToBeanBuilder<T>(in)
                .withSeparator(',')
                .withQuoteChar('\'')
                .withMappingStrategy(strategy).build();
        List<T> list= csvToBean.parse();
        System.out.println(System.currentTimeMillis());
        System.out.println(list.size());
    return list;    
        }

如果只需要取csv 中部分列的值映射到对象里,则只需要在对象中添加注解 @CsvBindByName即可

(required = true ) 参数指csv 中该列的值不能为空

public class Student {
     
    @CsvBindByName(column = "name", required = true)
    private String name;
    @CsvBindByName(column = "address", required = false)
    private String address;
    @CsvBindByName(column = "age", required = false)
    private Integer age;
    //不需要从csv中取值
		private Integer sex;

当然这样的取值还是不够自由,那么Opencsv还提供了更自由的方式

读取csv 的任意行和列。而且csv很大的话,速度也很快哦,只要内存跟得上。

minLine 为读取的起始行,当然你也可以再设置一个结束行的字段,每次判断行号。当然也需要自己设置一个行号,每次自增。

 private static Set<String> readCsv(int minLine,  String path) throws IOException {
     
        Integer lineNum = minLine;
        FileReader fReader = new FileReader(new File(path));
        CSVReader csvReader = new CSVReader(fReader);
        String[] values;
        Set<String> set = new HashSet<>();
        //跳过前方minLine 条数据
        csvReader.skip(minLine);
        while ((values = csvReader.readNext()) != null) {
     
                // values 是一个数组,存储了csv当前行的所有元素,在此你可以将数组中的元素取出来放入你的对象中
                set.add(StringUtils.join(values, Constants.CSV_SPLIT));
            lineNum++;
        }
        return set;
    }

写csv

	public static void main(String[] args) throws Exception {
     
		File file = new File("xxx.csv");
		Writer writer = new FileWriter(file);
    //分隔符默认为逗号
		CSVWriter csvWriter = new CSVWriter(writer);
		String[] strs = {
     "abc" , "abc" , "abc"};
		csvWriter.writeNext(strs);
		csvWriter.close();
	}

写 csv 方法2

此方法不用引入其他依赖,jdk自身的就够了,目前我使用此方法

controller 层

 @GetMapping("/csv")
    public void csv(HttpServletRequest request, HttpServletResponse response, String keyword) throws Exception{
       //查询数据库获取导出数据
        List list = xxxService.exportList(keyword);
        String fileName = ExportUtil.getFileName(request, "测试数据" + System.currentTimeMillis() + ".csv");
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
		// 表头
        LinkedHashMap header = new LinkedHashMap<>();
        header.put("1", "姓名");
        header.put("2", "年龄");
        header.put("3", "性别");
        header.put("4", "地址");
        List> data = new ArrayList<>();
        data.add(header);
        list.forEach(x->{
            LinkedHashMap body = new LinkedHashMap<>();
            body.put("1", x.getName());
            body.put("2", x.getAge());
            body.put("3", x.getSex());
            body.put("4", x.getAddress());
            data.add(body);
        });
        FileCopyUtils.copy(ExportUtil.exportCSV(data), response.getOutputStream());
    }

ExportUtil 工具类

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yyb
 * @time 2020/3/9
 */
public class ExportUtil {
    public static byte[] exportCSV(List> exportData) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        BufferedWriter buffCvsWriter = null;
        try {
            buffCvsWriter = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
            // 将body数据写入表格
            for (Iterator> iterator = exportData.iterator(); iterator.hasNext(); ) {
                fillDataToCsv(buffCvsWriter, iterator.next());
                if (iterator.hasNext()) {
                    buffCvsWriter.newLine();
                }
            }
            // 刷新缓冲
            buffCvsWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (buffCvsWriter != null) {
                try {
                    buffCvsWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return out.toByteArray();
    }

    private static void fillDataToCsv(BufferedWriter buffCvsWriter, LinkedHashMap row) throws IOException {
        Map.Entry propertyEntry;
        for (Iterator propertyIterator = row.entrySet().iterator(); propertyIterator.hasNext(); ) {
            propertyEntry = propertyIterator.next();
            buffCvsWriter.write("\"" + propertyEntry.getValue().toString() + "\"");
            if (propertyIterator.hasNext()) {
                buffCvsWriter.write(",");
            }
        }
    }

    public static  String getFileName(HttpServletRequest request, String name) throws UnsupportedEncodingException {
        String userAgent = request.getHeader("USER-AGENT");
        return userAgent.contains("Mozilla") ? new String(name.getBytes(), "ISO8859-1") : name;
    }
}

好了,打完收工。

你可能感兴趣的:(2.Java)