CSV:运用工厂模式读取csv文件(简洁安全可靠型设计)

闲暇之余,想撸一些代码,刚好想到appcheck扫描会扫描出项目中依赖的jar的Component、Vision、License信息,最终可以导出.csv格式文件,而.csv是免费的,所以写了个demo读取csv。
首先:我们创造一个CsvReader工厂类,来生产每一个CsvReader对象。代码简洁,就直接上代码了。

附上依赖:

        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>4.1</version>
        </dependency>
package com.reader.csv.csv;

import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.RFC4180Parser;
import com.opencsv.RFC4180ParserBuilder;
import com.reader.csv.util.IOUtils;
import com.reader.csv.util.UnicodeReader;
import java.io.*;

/**
 * @author lucas 2019/6/20 9:42
 * @version V1.0
 */
public class CsvReaderFactory {

    private File file;
    private String charSet;
    private static final String DEFAULT_CHAR_SET = "utf-8";
    private RFC4180Parser rfc4180Parser;
    private CSVReaderBuilder csvReaderBuilder;
    private FileInputStream fileInputStream;
    private CSVReader csvReader;

    public CsvReaderFactory(File file, String charSet){
        this.file = file;
        this.charSet = charSet;
    }
    public RFC4180Parser getRfc4180Parser(){
        if (null == this.rfc4180Parser) {
            this.rfc4180Parser = (new RFC4180ParserBuilder()).build();
        }
        return this.rfc4180Parser;
    }

    public static BufferedReader getReader(InputStream is, String charSet) {
        return is == null ? null : new BufferedReader(new UnicodeReader(is, charSet));
    }
    
    private CSVReaderBuilder getCsvReaderBuilder(){
        if (this.csvReaderBuilder == null) {
            this.csvReaderBuilder = new CSVReaderBuilder(IOUtils.getReader(getFileInputStream(), this.charSet == null?DEFAULT_CHAR_SET:this.charSet));
        }
        return  this.csvReaderBuilder;
    }

    public CSVReader getCsvReader(){
        if (csvReader == null) {
            this.csvReader = getCsvReaderBuilder().build();
        }
        return this.csvReader;
    }

    private FileInputStream getFileInputStream(){
        try {
            this.fileInputStream = new FileInputStream(this.file);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("file not found error", e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return this.fileInputStream;
    }

    public void close(){
        try {
            if (this.fileInputStream != null) {
                this.fileInputStream.close();
            }
            if (this.csvReader != null) {
                csvReader.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

我们既然有了CsvReader工厂类,生产CsvReader就只需要创造一个工厂类对象,就会生产一个CsvReader对象。但是这样无法保证每一个用工厂类的人会去调用close(),关闭InputStream和Reader,所以继续封装一层。

package com.reader.csv.csv;

import com.opencsv.CSVReader;
import java.io.File;
import java.util.List;

/**
 * <p>CsvReaderOutput</p>
 * @author lucas 2019/6/29 9:39
 * @version V1.0
 */
public class CsvReaderOutput {

    private List<String []> strings;
    private File file;
    private String charSet;
    private CsvReaderFactory csvReaderFactory;
    private CSVReader csvReader;
    public static final String CSV_FORMAT = ".csv";

    public CsvReaderOutput(File file, String charSet){
        this.charSet = charSet;
        this.file = file;
    }

    public List<String []> getStrings(){
        try {
            this.strings = getCsvReader().readAll();
        } catch (Exception e) {
        	throw new RuntimeException(e);
        } finally {
            this.csvReaderFactory.close();
        }
        return this.strings;
    }

    private CsvReaderFactory getCsvReaderFactory(){
        if (this.csvReaderFactory == null) {
            this.csvReaderFactory = new CsvReaderFactory(this.file, this.charSet);
        }
        return this.csvReaderFactory;
    }

    private CSVReader getCsvReader(){
        if (this.csvReader == null) {
            this.csvReader = getCsvReaderFactory().getCsvReader();
        }
        return this.csvReader;
    }
}


封装后可以直接获取到每一个csv文件的所有数据信息,放入List<String []>中,List对应行,String []对应每一列。

package com.reader.csv;

import com.reader.csv.csv.CsvReaderOutput;
import java.io.File;
import java.util.List;

/**
 * @author lucas 2019/6/28 11:52
 * @version V1.0
 */
public class CsvReaderTest {
    public static void main(String[] args){
        File[] list = new File("D:\\00csv").listFiles();
        for (File file : list) {
            if (file.isFile() && file.getName().endsWith(".csv")){
                CsvReaderOutput csvReaderOutput = new CsvReaderOutput(file, "utf-8");
                List<String[]> allLines = csvReaderOutput.getStrings();
                for (String[] strings :allLines) {
                    System.out.println(strings[0]);
                }
                break;
            }
        }
    }
}

用一个.csv格式文档测试一下,代码简洁可靠,更重要的是将close封装起来无需调用者自己去close(),避免了安全性问题。
当然,如果数据量非常大,这样的代码模式是不能满足的,需要自行扩展代码,利用缓存或边读边写的方式去进行。当然,这些代码也只是一个简单的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值