over 2 years ago

CSV常常做為資料交換的一種手段,透過第三方元件可加快開發速度與讀取速度,這邊紀錄用opencsv跟apache.commons.csv兩種不同的用法

假設我們有個CSV轉換後的目標物件

StockAlert.java
package com.sam.data;

import lombok.Data;

@Data
public class StockAlert {
    private String id;
    private String name;
    private String url;
}

下面是我們讀取對象CSV

id,name,url
1301,台塑,https://www.google.com.tw/alerts/feeds/14500439789290604405/2609808599257676796
1303,南亞,https://www.google.com.tw/alerts/feeds/14500439789290604405/6519899982382495908
1304,台聚,https://www.google.com.tw/alerts/feeds/14500439789290604405/11900768765428460088
1305,華夏,https://www.google.com.tw/alerts/feeds/14500439789290604405/16872102119975357308
1307,三芳,https://www.google.com.tw/alerts/feeds/14500439789290604405/6519899982382493936

在opencsv部分可透過下面方法來轉換

build.gradle
compile 'net.sf.opencsv:opencsv:2.+'

工具

Opencsv.java
package com.sam.utils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.bean.CsvToBean;
import au.com.bytecode.opencsv.bean.HeaderColumnNameMappingStrategy;

public class Opencsv {

    public static <T> List<T> parseFileToBeans(final String filepath, final char fieldDelimiter, final Class<T> beanClass) throws IOException{
        //改用NIO方式讀檔

        Path file = Paths.get(filepath);
        BufferedReader br = Files.newBufferedReader(file, StandardCharsets.UTF_8);
        //傳統讀檔方式

        //BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filepath), StandardCharsets.UTF_8));

        List<T> relist = parseBufferedReaderToBeans(br, fieldDelimiter, beanClass);
        br.close();
        return relist;
    }

    public static <T> List<T> parseResourceToBeans(final String filepath, final char fieldDelimiter, final Class<T> beanClass) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(ClassLoader.class.getResourceAsStream(filepath), "UTF-8"));
        List<T> relist = parseBufferedReaderToBeans(br, fieldDelimiter, beanClass);
        br.close();
        return relist;
    }

    public static <T> List<T> parseBufferedReaderToBeans(final BufferedReader br, final char fieldDelimiter, final Class<T> beanClass){
        CSVReader reader = null;
        List<T> relist = null;
        try {
            reader = new CSVReader(br, fieldDelimiter);
            final HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<T>();
            strategy.setType(beanClass);
            final CsvToBean<T> csv = new CsvToBean<T>();
            relist = csv.parse(strategy, reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return relist;
    }
}

使用方式

TestLoad.java
package com.sam.gettest;

import java.io.IOException;
import java.util.List;

import com.sam.data.StockAlert;
import com.sam.utils.Opencsv;

public class TestLoad {
    public static void main(String[] args) {
        try {
            List<StockAlert> list = Opencsv.parseFileToBeans("D:/stockalert.txt", ',', StockAlert.class);
            for(StockAlert alert:list){
                System.out.println(String.format("id=%s , name=%s , url=%s", alert.getId(), alert.getName(), alert.getUrl()));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在apache.commons.csv部分則要這樣使用

compile 'org.apache.commons:commons-csv:1.+'

下面是已經包裝好的工具

Apachecsv.java
package com.sam.utils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import org.apache.commons.csv.*;

public class Apachecsv {

    public static List<CSVRecord> parseFileToBeans(final String filepath) throws IOException{
        Path file = Paths.get(filepath);
        BufferedReader br = Files.newBufferedReader(file, StandardCharsets.UTF_8);
        List<CSVRecord> relist = parseBufferedReaderToBeans(br);
        br.close();
        return relist;
    }

    public static List<CSVRecord> parseBufferedReaderToBeans(final BufferedReader br){
        CSVParser parser = null;
        List<CSVRecord> records = null;
        try {
            parser = new CSVParser(br, CSVFormat.DEFAULT.withHeader());
            records = parser.getRecords();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(parser!=null)
                    parser.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return records;
    }
}

讀檔跟寫檔的使用

TestLoad2.java
package com.sam.gettest;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import org.apache.commons.csv.*;
import com.sam.utils.Apachecsv;

public class TestLoad2 {
    private static final Object [] FILE_HEADER = {"stockid", "stockname", "alerturl"};
    private static final String NEW_LINE_SEPARATOR = System.getProperty("line.separator");

    public static void main(String[] args) throws IOException {
        //讀檔

        List<CSVRecord> list = Apachecsv.parseFileToBeans("D:/stockalert.txt");
        for (CSVRecord record : list) {
            System.out.printf("%s %s %s\n", record.get("id"), record.get("name"), record.get("url"));
        }
        //寫檔

        CSVPrinter csvFilePrinter = null;
        CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);
        Path target = Paths.get("D:/test.csv");
        if(Files.notExists(target)){
            Files.createFile(target);
        }
        BufferedWriter writer = Files.newBufferedWriter(target, StandardCharsets.UTF_8, StandardOpenOption.WRITE);

        //initialize CSVPrinter object

        csvFilePrinter = new CSVPrinter(writer, csvFileFormat);
        //Create CSV file header

        if(list.size() > 0){
            CSVRecord tmp = list.get(0);
            csvFilePrinter.printRecord(tmp.toMap().keySet());
        }else{
            csvFilePrinter.printRecord(FILE_HEADER);
        }
        //Write a new object list to the CSV file

        for (CSVRecord record : list) {
            List dataRecord = new ArrayList();
            for(int i=0;i<record.size();i++){
                dataRecord.add(record.get(i).trim());
            }
            csvFilePrinter.printRecord(dataRecord);
        }
        writer.flush();
        writer.close();
        csvFilePrinter.close();
    }
}
← 使用Spring-Batch進行排程工作 Run code at Spring Boot startup →
 
comments powered by Disqus