大批量数据导出csv,平替导出excel性能优化解决方案封装工具类

这篇具有很好参考价值的文章主要介绍了大批量数据导出csv,平替导出excel性能优化解决方案封装工具类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

阿丹:

        有些业务逻辑需要在导出非常大量的数据,几百甚至几千万的数据这个时候再导出excel来对于性能都不是很友好,这个时候就需要替换实现思路来解决这个问题。

        本文章提供了两种解决的方案,也是两种从数据库中拿取数据的方式一种是原生的jdbc一种是使用mybatis来封装对象来完成的。文章来源地址https://www.toymoban.com/news/detail-793315.html

使用字符串数组的导出:

package com.lianlu.export.util;

import org.apache.poi.ss.formula.functions.T;

import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * CSV导出工具类,用于将数据列表导出为CSV文件。
 */
public class CSVExportUtil {

    /**
     * 导出CSV文件。
     *
     * @param dataList          需要导出的内容,类型为字符串数组的列表。
     * @param validationRulesMap 校验和替换规则的映射,键为列索引,值为一个映射,其中键为需要替换的字符串,值为替换后的字符串。
     * @param headers           CSV文件的表头,类型为字符串数组。
     * @param fileName          导出CSV文件的名称。
     * @throws IOException 如果在写入文件过程中发生异常。
     */
    public static void exportCSV(List<String[]> dataList, Map<Integer, Map<String, String>> validationRulesMap, String[] headers, String fileName) throws IOException {
        // 预处理数据(校验和替换)
        List<String[]> preprocessedDataList = preprocessData(dataList, validationRulesMap);

        // 写入CSV文件
        writeCSVToFile(preprocessedDataList, headers, fileName);
    }

    /**
     * 不需要替换规则的导出
     * @param dataList
     * @param headers
     * @param fileName
     * @throws IOException
     */
    public static void exportCSV(List<String[]> dataList, String[] headers, String fileName) throws IOException {
        // 写入CSV文件
        writeCSVToFile(dataList, headers, fileName);
    }

        /**
         * 预处理数据列表(校验和替换)。
         *
         * @param dataList          原始数据列表。
         * @param validationRulesMap 校验和替换规则的映射。
         * @return 预处理后的数据列表。
         */
    private static List<String[]> preprocessData(List<String[]> dataList, Map<Integer, Map<String, String>> validationRulesMap) {
        return dataList.stream()
                .map(row -> preprocessDataRow(row, validationRulesMap))
                .collect(Collectors.toList());
    }

    /**
     * 预处理单行数据(校验和替换)。
     *
     * @param row               单行数据。
     * @param validationRulesMap 校验和替换规则的映射。
     * @return 预处理后的单行数据。
     */
    private static String[] preprocessDataRow(String[] row, Map<Integer, Map<String, String>> validationRulesMap) {
        for (Map.Entry<Integer, Map<String, String>> entry : validationRulesMap.entrySet()) {
            int columnIndex = entry.getKey();
            Map<String, String> rules = entry.getValue();

            String originalValue = row[columnIndex];
            String replacedValue = rules.getOrDefault(originalValue, originalValue);

            row[columnIndex] = replacedValue;
        }
        return row;
    }

    /**
     * 将预处理后的数据写入CSV文件。
     *
     * @param dataList   预处理后的数据列表。
     * @param headers    CSV文件的表头。
     * @param fileName   导出CSV文件的名称。
     * @throws IOException 如果在写入文件过程中发生异常。
     */
    private static void writeCSVToFile(List<String[]> dataList, String[] headers, String fileName) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            // 写入表头
            writer.write(String.join(",", headers));
            writer.newLine();

            // 分批写入数据以提高性能
            AtomicInteger counter = new AtomicInteger(0);
            while (counter.get() < dataList.size()) {
                int batchSize = Math.min(10000, dataList.size() - counter.get()); // 每次写入10000条数据,可根据实际需求调整
                List<String[]> batchData = dataList.subList(counter.get(), counter.get() + batchSize);

                for (String[] dataRow : batchData) {
                    writer.write(String.join(",", dataRow));
                    writer.newLine();
                }
                counter.addAndGet(batchSize);
            }
        }


    }
    /**
     * 从泛型对象中获取属性值并转换为字符串数组。
     *
     * @param data 泛型对象
     * @return 字符串数组,包含对象的属性值
     */
    private String[] convertObjectToArray(T data) {
        Class<?> clazz = data.getClass();
        Field[] fields = clazz.getDeclaredFields();

        // 获取对象的所有字段,并设置它们为可访问
        for (Field field : fields) {
            field.setAccessible(true);
        }

        String[] rowData = new String[fields.length];

        // 遍历所有字段,获取每个字段的值并添加到字符串数组中
        for (int i = 0; i < fields.length; i++) {
            try {
                rowData[i] = fields[i].get(data).toString();
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Failed to access field value", e);
            }
        }
        return rowData;
    }





}

通过对象的导出:

package com.lianlu.export.util;


import java.io.*;
import java.lang.reflect.Field;
import java.util.*;

public class CSVExportUtil<T> {

    /**
     * 导出CSV文件。
     *
     * @param dataList       需要导出的数据列表(泛型对象列表)
     * @param validationRulesMap 校验和替换规则映射(键为列索引,值为校验和替换规则的映射)
     * @param headers         CSV表头数组
     * @param fileName        导出CSV文件的名称
     * @throws IOException 如果在写入文件时发生错误
     */
    public void exportCSV(List<T> dataList, Map<Integer, Map<String, String>> validationRulesMap, String[] headers, String fileName) throws IOException {
        // 预处理数据(校验和替换)
        List<String[]> preprocessedData = preprocessData(dataList, validationRulesMap);

        // 写入CSV文件
        writeCSV(preprocessedData, headers, fileName);
    }

    /**
     * 预处理数据(校验和替换)。
     *
     * @param dataList       数据列表(泛型对象列表)
     * @param validationRulesMap 校验和替换规则映射(键为列索引,值为校验和替换规则的映射)
     * @return 预处理后的数据(字符串数组列表)
     */
    private List<String[]> preprocessData(List<T> dataList, Map<Integer, Map<String, String>> validationRulesMap) {
        List<String[]> preprocessedData = new ArrayList<>(dataList.size());
        for (T data : dataList) {
            String[] rowData = convertObjectToArray(data);
            preprocessedData.add(validateAndReplace(rowData, validationRulesMap));
        }
        return preprocessedData;
    }

    /**
     * 从泛型对象中获取属性值并转换为字符串数组。
     *
     * @param data 泛型对象
     * @return 字符串数组,包含对象的属性值
     */
    private String[] convertObjectToArray(T data) {
        Class<?> clazz = data.getClass();
        Field[] fields = clazz.getDeclaredFields();

        // 获取对象的所有字段,并设置它们为可访问
        for (Field field : fields) {
            field.setAccessible(true);
        }

        String[] rowData = new String[fields.length];

        // 遍历所有字段,获取每个字段的值并添加到字符串数组中
        for (int i = 0; i < fields.length; i++) {
            try {
                rowData[i] = fields[i].get(data).toString();
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Failed to access field value", e);
            }
        }

        return rowData;
    }

    /**
     * 根据提供的校验和替换规则对字符串数组进行校验和替换。
     *
     * @param rowData   字符串数组
     * @param rulesMap 校验和替换规则映射(键为列索引,值为校验和替换规则的映射)
     * @return 校验和替换后的字符串数组
     */
    private String[] validateAndReplace(String[] rowData, Map<Integer, Map<String, String>> rulesMap) {
        for (Map.Entry<Integer, Map<String, String>> entry : rulesMap.entrySet()) {
            int columnIndex = entry.getKey();
            Map<String, String> ruleMap = entry.getValue();
            String currentValue = rowData[columnIndex];
            if (ruleMap.containsKey(currentValue)) {
                rowData[columnIndex] = ruleMap.get(currentValue);
            }
        }
        return rowData;
    }

    /**
     * 将预处理后的数据写入CSV文件。
     *
     * @param preprocessedData 预处理后的数据(字符串数组列表)
     * @param headers          CSV表头数组
     * @param fileName         导出CSV文件的名称
     * @throws IOException 如果在写入文件时发生错误
     */
    private void writeCSV(List<String[]> preprocessedData, String[] headers, String fileName) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            CSVWriter csvWriter = new CSVWriter(writer);

            // 写入表头
            csvWriter.writeNext(headers);

            // 写入数据
            csvWriter.writeAll(preprocessedData);

            csvWriter.close();
        }
    }
}

到了这里,关于大批量数据导出csv,平替导出excel性能优化解决方案封装工具类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Jmeter(三十一):制造大批量的用户数据数据

    需求:因测试需要,要造100w用户数据,通过用户名、手机号、密码可新增用户,其中用户名和电话号码要求100w用户不能重复 要点: 1、通过Bean shell Sampler实现用户名和手机号的足够随机。 符合我们常用规则的手机号:第一位为1,第二位为3-9,后面的9位为0-9即可。 phone=${_

    2024年02月10日
    浏览(41)
  • MySQL---使用索引优化、大批量插入数据优化

    1. 使用索引优化 索引是数据库优化最常用也是最重要的手段之一 , 通过索引通常可以帮助用户解决大多数的 MySQL 的性能优化问题: 1.1 避免索引失效应用-全值匹配 该情况下,索引生效,执行效率高。 1.2 避免索引失效应用-最左前缀法则 1.3 避免索引失效应用-其他匹配原则

    2024年02月07日
    浏览(51)
  • redis 无占用 两种方式 清除大批量数据 lua脚本

    redis存储了很多无用的key,占用了大量内存,需要清除 第一种 (颗粒度较大) lua脚本,删除某些规则的key,输入删除的key,返回删除的符合规则的key的数量 弊端:颗粒度比较大,发送一个lua脚本去执行,会占用较多时间,堵塞其他redis命令 java代码 这样直接删除,因为规则有很

    2024年04月28日
    浏览(35)
  • 【sgTransfer】自定义组件:带有翻页、页码、分页器的穿梭框组件,支持大批量数据的穿梭显示。

      特性:   表格宽度可以自定义 翻页器显示控件可以自定义 列配置项可以设置显示字段列名称、宽度、字段名 可以配置搜索框提示文本,支持搜索过滤 穿梭框顶部标题可以自定义 左右箭头按钮文本可以设置

    2024年02月10日
    浏览(53)
  • 如何使用python快速将大批量图片合成为视频?

    由于CSDN大批量导入图片容易出现乱序,本程序将支撑图片转为视频,便于用视频的方式展示文件内容。 由于图片名称复杂多样,为便于统一化处理,增强程序的通用性,使用改名程序可以降低手动调整的复杂度。 改名之后的效果: 注意此部分的图片大小仍需要手动修改或输

    2024年02月04日
    浏览(46)
  • cesium实现大批量POI点位聚合渲染优化方案

    cesium目前只提供了entityCluster这个聚合类,使打点聚合更方便快捷的实现,但是一般在真正做项目的时候,大家会经常碰到成千上万个甚至几十万个点位需要聚合打点,那这时候你如果还是用entity去实现的话,怕是要被用户按在地上疯狂摩擦,摩擦。。。😅 我们可以通过模拟

    2024年02月09日
    浏览(40)
  • 远程运维大批量IT设备?向日葵批量部署、分组授权与安全功能解析

    数字化转型的不断推进,给予了企业全方位的赋能,但任何发展都伴随着成本与代价,比如在数字化转型过程中企业内部办公与外部业务所需的不断增加的IT设备数量,就为日常的运维工作提出了更大的挑战。 针对企业面对海量IT设备时的运维难、效率低、容易出错等问题,

    2024年02月14日
    浏览(45)
  • 使用postman做接口测试传入大批量动态参数的方法

    postman是一个非常好用的接口测试工具,而且功能也很强大,今天只简单说一下使用postman如何对一个接口传入大批量参数进行测试的方法。 以我测试的平台为例,我们的平台是做在线教育平台的,我模拟的场景是老师有一门课叫ABC,现在需要有1000个学生加入ABC这门课。我们不

    2024年01月23日
    浏览(59)
  • 记一次 OSS 大批量文件下载的实现 → bat脚本不好玩!

    一天夜里,侄女跟我哥聊天 侄女一脸期待的看着我哥:爸爸,你说妈妈和奶奶谁漂亮啊? 我哥不慌不忙的拿起一粒瓜子,轻声说道:为啥没有你啊? 侄女笑容渐起,似乎得到了她想要的回答,仍继续问道:那妈妈和奶奶还有我,谁漂亮? 我哥瞄了一眼侄女,又拿起一粒瓜子

    2024年02月05日
    浏览(42)
  • ZooKeeper+Kafka+ELK+Filebeat集群搭建实现大批量日志收集和展示

    大致流程:将nginx 服务器(web-filebeat)的日志通过filebeat收集之后,存储到缓存服务器kafka,之后logstash到kafka服务器上取出相应日志,经过处理后写入到elasticsearch服务器并在kibana上展示。 一、集群环境准备 二、搭建zookeeper集群 前提条件:三台机器分别修改时区、关闭防火墙

    2024年02月04日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包