【Java】CSV文件的读写

一、简述

日常开发中,把数据做成表格输出和导出非常常见。那表格输出有Excel格式(例如 xx.xlsx),也有最简单的CSV格式。对比常见的Excel格式的表格,CSV的导入导出不需要增加额外依赖,全平台通用,适合于数据结构简单、快速开发和大数据场景。

二、CSV文件的读取

上代码

  /**
     * CSV文件读取
     * @param file 文件,包含完整路径
     * @param charset 文件编码
     * @return 读取的结果集
     */
    public static List> read(String file, Charset charset) {
        List> res = new ArrayList<>();
        try (FileInputStream inputStream = new FileInputStream(file); BufferedReader sc = new BufferedReader(new InputStreamReader(inputStream, charset))) {
            String line;
            while ((line = sc.readLine()) != null) {
                res.add(handleCSVString(line));
            }
        } catch (IOException ignored) {

        }
        return res;
    }

    /**
     * 处理读取到的字符串
     * @param string 字符串
     * @return 解析后的数据
     */
    private static List handleCSVString(String string) {
        List res = new ArrayList<>();
        StringBuilder stringBuilder = new StringBuilder();
        int start = 0;
        boolean escape = false;
        while (start < string.length()) {
            char ch = string.charAt(start ++);
            switch (ch) {
                case ',':
                    if (!escape) {
                        res.add(handleSplitString(stringBuilder));
                        stringBuilder = new StringBuilder();
                    } else {
                        stringBuilder.append(ch);
                    }
                    break;
                case '"':
                    if (escape) {
                        stringBuilder.append(ch);
                        escape = false;
                    } else {
                        escape = true;
                    }
                    break;
                default:
                    stringBuilder.append(ch);
                    break;
            }
        }
        res.add(handleSplitString(stringBuilder));
        return res;
    }

    /**
     * 处理分割后的字符串,去除双引号
     * @param stringBuilder 字符串
     * @return 处理结果
     */
    private static String handleSplitString(StringBuilder stringBuilder) {
        String str = stringBuilder != null ? stringBuilder.toString() : "";
        if (!str.isEmpty() && str.charAt(str.length() - 1) == '"') {
            str = str.substring(0, str.length() - 1);
        }
        return str;
    }

注意点:
1、字符编码
2、逗号和双引号对于CSV而言是特殊字符,含有逗号和双引号的字符串需要做转义

三、CSV文件的写入

上代码

 /**
     * 写文件
     * @param dataList 数据集
     * @param file 文件,包含完整路径
     * @param charset 文件字符编码
     * @return 结果
     */
    public static boolean write(List> dataList, String file, Charset charset) {
        boolean isSuccess = false;
        try (OutputStream fileOutStream = new FileOutputStream(file);
             OutputStreamWriter fileOutStreamWriter = new OutputStreamWriter(fileOutStream, charset);
             BufferedWriter fileWriter = new BufferedWriter(fileOutStreamWriter)) {

            for (List strs : dataList) {
                fileWriter.write(handleToCSVString(strs));
                fileWriter.newLine();
            }
            isSuccess = true;
        } catch (IOException ignored) {

        }
        return isSuccess;
    }

    /**
     * 处理每行数据
     * @param strings 数据
     * @return CSV格式的字符串
     */
    private static String handleToCSVString(List strings) {
        if (strings == null || strings.isEmpty()) {
            return "";
        }

        StringBuilder newStr = new StringBuilder();
        for (String ss : strings) {
            if (ss.contains(",") || ss.contains("\"")) {
                newStr.append(escapeCSVString(ss)).append(",");
            } else {
                newStr.append(ss).append(",");
            }
        }

        return newStr.toString().substring(0, newStr.length() - 1);
    }

    /**
     * 转义CSV字符串:双引号做特殊处理
     * @param string 要转义的字符串
     * @return 转义后结果
     */
    private static String escapeCSVString(String string) {
        StringBuilder res = new StringBuilder();
        res.append('"');
        int index = 0;
        while (index < string.length()) {
            char ch = string.charAt(index++);
            if (ch == '"') {
                res.append('"').append('"');
            } else {
                res.append(ch);
            }
        }
        res.append('"');
        return res.toString();
    }

注意文件的编码,如果有乱码,检查一下编码是否一致

你可能感兴趣的:(【Java】CSV文件的读写)