Bootstrap

Java操作csv文件(根据类进行读取和输出到csv文件)

看过博主文章都知道,博主不太喜欢废话,讲究实用。避开长篇大论,直接上各位老爷最喜欢的实操代码。关键点都在代码注释中!!

一,代码准备

首先准备依赖
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-csv</artifactId>
      <version>1.10.0</version>
    </dependency>
    <dependency>
      <groupId>com.opencsv</groupId>
      <artifactId>opencsv</artifactId>
      <version>5.7.1</version>
    </dependency>
准备启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class Applications {

    public static void main(String[] args) {
         SpringApplication.run(Applications.class, args);
    }
}
准备关键操作csv的util文件
import com.opencsv.CSVWriter;
import com.opencsv.CSVWriterBuilder;
import com.opencsv.ICSVWriter;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;

import java.io.*;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class CsvUtil {

    /**
     * 根据指定的类读取csv文件
     *
     * @param filepath 文件路径
     * @param clazz 读取类
     * @param startLine 开始行
     * @return
     * @param <T>
     */
    public static <T> List<T> CSVToBean(String filepath, Class<T> clazz, int startLine) throws IOException {
        BufferedReader reader = createBufferedReader(filepath);
        try {
            CsvToBean<T> csvToBean = new CsvToBeanBuilder<T>(reader).withType(clazz) // 映射的目标类型
                    .withIgnoreLeadingWhiteSpace(true) //忽略 CSV 文件中每行开头的空白字符。
                    .withSkipLines(startLine)  // 从第几行开始读取数据
                    .withIgnoreEmptyLine(true) // 忽略空行
                    .build();
            List<T> resultObj = csvToBean.parse();
            return resultObj;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            reader.close();
        }

    }

    private static BufferedReader createBufferedReader(String filepath) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(filepath);
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
        return new BufferedReader(inputStreamReader);
    }

    private static BufferedWriter createBufferedWriter(String filepath) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(filepath);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
        return new BufferedWriter(outputStreamWriter);
    }

    /**
     * 写为csv文件
     *
     * @param filepath
     * @param content
     */
    public static void writeToFile(String filepath, Object content) throws IOException {
        BufferedWriter bufferedWriter = createBufferedWriter(filepath);
        try {
            if (content instanceof List) {
                writeList(bufferedWriter, (List<Object>) content);
            } else {
                writeSingle(bufferedWriter, content);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            bufferedWriter.flush();
            bufferedWriter.close();
        }
    }

    private static void writeList(BufferedWriter bufferedWriter, List<Object> content) throws IOException {
        CSVWriter csvWriter = new CSVWriter(bufferedWriter);

        try {
            /**
             * 方法一:简单输出为一行 或者输出为多行
             */
            String[] strings = new String[content.size()];
            for (int i = 0; i < content.size(); i++) {
                strings[i] = content.get(i).toString();
                // 输出到多行
    //            csvWriter.writeNext(new String[]{strings[i]});
            }
            // 只会输出到一行
//        csvWriter.writeAll(Collections.singleton(strings));

            /**
             * 方法二: 输出格式按csv的格式
             */
            for (Object e : content) {
                Method[] methods = e.getClass().getMethods();
                List<String> list = new ArrayList<>();

                // 遍历所有方法
                for (Method method : methods) {
                    // 如果方法是 getter 方法(以 "get" 或 "is" 开头,并且没有参数)
                    if (isGetter(method)) {
                        try {
                            // 调用 getter 方法获取属性值
                            String value = String.valueOf(method.invoke(e));
                            // 加入list
                            list.add(value);
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    }
                }
                writeForList(csvWriter, list);
                list.clear();
            }
        } finally {
            csvWriter.flush();
            csvWriter.close();
        }
    }

    private static void writeForList(CSVWriter csvWriter, List<String> list) {
        String[] array = list.toArray(new String[0]);
        csvWriter.writeNext(array);
    }

    // 判断方法是否为 getter 方法
    private static boolean isGetter(Method method) {
        String name = method.getName();
        return (name.startsWith("get") || name.startsWith("is"))
                && !name.startsWith("getClass")
                && method.getParameterCount() == 0
                && !void.class.equals(method.getReturnType());
    }

    private static void writeSingle(BufferedWriter bufferedWriter, Object content) throws Exception {
        ICSVWriter writer = new CSVWriterBuilder(bufferedWriter)
                .withSeparator(',')
                .withQuoteChar('"')
                .withEscapeChar('\\')
                .withLineEnd("\n")
                .build();
        StatefulBeanToCsv<Object> beanToCsv = new StatefulBeanToCsvBuilder<Object>(writer)
                .build();

        // 将对象列表写入 CSV 文件
        beanToCsv.write(content);
    }
}
准备测试用的model类
import com.opencsv.bean.CsvBindByName;
import com.opencsv.bean.CsvBindByPosition;
import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class RojerCSVModel {

    /**
     *  @CsvBindByName注解是根据 CSV 文件中的列名进行绑定
     *  @CsvBindByPosition根据 CSV 文件中的位置(在哪一列)进行绑定
     */
//    @CsvBindByName(column = "Name", required = false)
    @CsvBindByPosition(position = 0, required = false)
    private String name;

//    @CsvBindByName(column = "Age", required = false)
    @CsvBindByPosition(position = 1, required = false)
    private String age;

//    @CsvBindByName(column = "Address", required = false)
    @CsvBindByPosition(position = 2, required = false)
    private String address;

    @Override
    public String toString() {
        return   name  +',' +  age +  ','  + address;
    }
准备测试用的controller类
import com.luojie.moudle.RojerCSVModel;
import com.luojie.util.CsvUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class CSVTestController {

    @GetMapping("/csv/test")
    public void testCsv() throws Exception {
        RojerCSVModel csvModel1 = new RojerCSVModel("John", "30", "New York");
        RojerCSVModel csvModel2 = new RojerCSVModel("Alice", "25", "London");
        RojerCSVModel csvModel3 = new RojerCSVModel("Rojer", "27", "Shang Hai");
        List<RojerCSVModel> list = new ArrayList<>();
        list.add(csvModel1);
        list.add(csvModel2);
        list.add(csvModel3);
        // 测试写一个的情况
//        CsvUtil.writeToFile("D:\\tmp\\test1.csv", csvModel1);
        CsvUtil.writeToFile("D:\\tmp\\test1.csv",list);
    }

    @GetMapping("/csv/test/get")
    public void testCsvGet() throws Exception {
        List<RojerCSVModel> list = new ArrayList<>();
        list = CsvUtil.CSVToBean("D:\\tmp\\test1.csv", RojerCSVModel.class, 0);
        System.out.println(list.size());
    }
}
记得在对应测试路径下准备csv文件

如果不想自己创,可以自己再写个方法去检测如无则创建!

二,代码测试

测试单类写入的情况(调用过程就不展示了)

结果

测试为list时的写入情况

测试读取为list<obj>的情况

希望对各位看官老爷有帮助,如果可以的话,能否请各位老爷点个赞,关注一下博主呢,在这里非常感谢各位老爷了。

;