桥山之巅,姬水之畔

JAVA操作CSV

2019.08.14

记录一下java 操作csv的代码。

1. 引入jar包

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

2. 创建csv

package com.ysl;

import com.csvreader.CsvWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.http.HttpServletResponse;

import com.ysl.CsvUtil;

/**
 * 创建csv
 * @author YSL
 */
public class CsvWriter {
    public static void main(String[] args) throws IOException {

        // 方式1. 直接创建本地的csv文件
        localFileCsv();

        // 方式2. 通过网页返回csv
        webResponseCsv(res);

    }

    public static void localFileCsv() throws IOException {
        String filePath = "/home/yang/桌面/test-中文.csv";

        // 创建CSV写对象
        CsvWriter csvWriter = new CsvWriter(filePath,',', Charset.forName("GBK"));
        // CsvWriter csvWriter = new CsvWriter(filePath); // 会中文乱码

        // 表头
        String[] headers = {"列1","列2","列3\n"};
        csvWriter.writeRecord(headers);
        csvWriter.writeRecord(new String[]{"value1", "value2", "value3" + "\n"});
        csvWriter.writeRecord(new String[]{"value1", "value2", "中文" + "\n"});
        csvWriter.writeRecord(new String[]{"value1", "value2", "中文"});
        csvWriter.writeRecord(new String[]{"value1", "value2", "中文" + "\n"});
        csvWriter.close();
    }

    public static void webResponseCsv(HttpServletResponse response) {
        // 导出csv 。CsvUtil见下文
        CsvUtil.writeCsv("文件名称", response, new CsvUtil.WriteCsv() {
            @Override
            public void write(CsvWriter csvWriter) throws IOException {
                // csv表头
                csvWriter.writeRecord(new String[]{"列1","列2","列3",});
                csvWriter.write("val1");
                csvWriter.write("val2");
                csvWriter.write("值3");
                csvWriter.endRecord();
            }
        });
    }
    
}

3. 读取csv

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import com.ysl.CsvUtil;

/**
 * 读取csv
 */
public class CsvReader {
    public static void main(String[] args) throws IOException {
        // 这里需要注意csv文件需要保存为utf-8格式————可以用记事本打开,然后另存为,选择utf-8格式
        InputStream in = getResourcesFileInputStream("test-中文.csv");
        // 读取csv
        List<String[]> records = CsvUtil.readCsv(in);
    }
    
    /**
     * 加载Resources目录下的文件
     * @param fileName 文件名
     * @return
     */
    public static InputStream getResourcesFileInputStream(String fileName){
        // Resources目录的绝对路径
        // String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);
        return in;
    }

}

4. CsvUtil工具类

package com.ysl;

import com.csvreader.CsvWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.Charset;

/**
 * Csv工具类
 * @author:YSL
 */
public class CsvUtil {

    private static Logger logger = LoggerFactory.getLogger(CsvUtil.class);
    private static String DEFAULT_ENCODE = "UTF-8";
    private static String GBK_ENCODE = "GBK";

    /*
    * 自定义write csv 接口
    */
    public interface WriteCsv {
        void write(CsvWriter csvWriter) throws Exception;
    }

    /**
     * 导出csv
     * @param  fileName 文件名称(不包括.csv后缀)
     * @param  response
     * @param  writeCsv 自定义接口,需实现write方法
     * @return 直接将csv返回给前端
     * @author YSL
     */
    public static void writeCsv(String fileName, HttpServletResponse response, CsvUtil.WriteCsv writeCsv){

        try {
            // 创建临时文件
            File tempfile = File.createTempFile(fileName, ".csv");

            // 创建 CsvWriter 对象
            CsvWriter csvWriter = new CsvWriter(tempfile.getCanonicalPath(),',', Charset.forName(GBK_ENCODE));

            // 接口需要实现的方法
            writeCsv.write(csvWriter);

            // 关闭 CsvWriter 对象
            csvWriter.close();

            // 获取写入数据的临时文件
            File fileLoad=new File(tempfile.getCanonicalPath());

            // 返回给前端
            CsvUtil.downLoadCsv(fileName+".csv", fileLoad, response);
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 导出csv文件
     * @param fileName 文件名称,含后缀
     * @param fileLoad 要输出的文件
     * @param response
     * @author YSL
     */
    public static void downLoadCsv(String fileName, File fileLoad, HttpServletResponse response) {

        try {
            byte[] b=new byte[1024 * 1024];
            OutputStream out=response.getOutputStream();
            response.reset();
            response.setContentType("application/csv");
            //re.setContentType("application/x-msdownload;");
            response.setHeader("content-disposition", "attachment; filename="+ URLEncoder.encode(fileName,DEFAULT_ENCODE));
            Long filelength=fileLoad.length();
            response.setHeader("Content_Length",String.valueOf(filelength));
            FileInputStream fileInputStream=new FileInputStream(fileLoad);
            int n;
            while ((n = fileInputStream.read(b)) != -1) {
                out.write(b, 0, n); //每次写入out1024字节
            }
            // System.out.println(tempfile.getCanonicalPath());
            fileInputStream.close();
            out.flush();
            out.close();
            logger.info("export:"+fileName+" --- success");
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
    }


    /**
     * 导出csv文件
     * @param fileName 文件名称,含后缀
     * @param content 逗号隔开的值,换行符:\r\n
     * @param response
     * @author YSL
     */
    public static void downLoadCsv(String fileName, String content, HttpServletResponse response) {

        try {
            OutputStream out = response.getOutputStream();
            //response.reset();
            response.setContentType("application/csv");
            response.setHeader("content-disposition", "attachment; filename="+StringUtil.encode(fileName,Constants.DEFAULT_GLOBAL_ENCODE));
            response.setHeader("Content_Length",String.valueOf(content.length()));
            out.write(content.getBytes(GBK_ENCODE));
            out.close();
            logger.info("export"+fileName+"success");
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
    }

	/**
     * 读csv
     * @param in
     * @return
     * @author YSL
     * @throws IOException
     */
    public static List<String[]> readCsv(InputStream in) throws IOException {

        List<String[]> records = new ArrayList<String[]>();
        String record;
        // 设定UTF-8字符集,使用带缓冲区的字符输入流BufferedReader读取文件内容
        BufferedReader file = new BufferedReader(new InputStreamReader(in, "UTF-8"));
        // file.readLine(); //跳过表头所在的行

        // 遍历数据行并存储在名为records的ArrayList中,每一行records中存储的对象为一个String数组
        while ((record = file.readLine()) != null) {
            String fields[] = record.split(",");
            records.add(fields);
        }
        // 关闭文件
        file.close();
        in.close();

        return records;
    }

}