java csv导入千万数据

依赖

       <dependency>
            <groupId>de.siegmar</groupId>
            <artifactId>fastcsv</artifactId>
            <version>1.0.3</version>
        </dependency>

controller层

@Slf4j
@RestController
public class CsvImportController {


    @PostMapping("csv")
    public Result csvImport(
            @RequestParam MultipartFile file ){
        System.out.println("进来了====");

        File fileToFile = multipartFileToFile(file);

        CsvReader csvReader = new CsvReader();
        csvReader.setContainsHeader(true);
        CsvContainer csv = null;
        try {
            csv = csvReader.read(fileToFile, StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List add = new ArrayList();
        for (CsvRow row : csv.getRows()) {
            //通过头获取对应属性
            String str=row.getField("userid");
            System.out.println("str  ==="+str);
            add.add(str);
        }


        return Result.ok(add);
    }

    public static File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        if (StringUtils.isEmpty(fileName)) {
            return null;
        }
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            log.error("MultipartFile转换为File转换异常:" + e.getMessage());
        }
        return null;
    }

}

 public static void main(String[] args) throws IOException {
        File file = new File("xxxx (7).csv");
        CsvReader csvReader = new CsvReader();
        csvReader.setContainsHeader(true);
        CsvContainer csv = csvReader.read(file, StandardCharsets.UTF_8);
        for (CsvRow row : csv.getRows()) {
            //通过头获取对应属性
            String str=row.getField("userid");
            System.out.println("str  ==="+str);
        }

    }

批量新增入库

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.4</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>3.4.3.4</version>
        </dependency>

实体映射类

@Data
@EqualsAndHashCode(callSuper = false)
@TableName("conf_user")
public class ConfUser {
    private static final long serialVersionUID = 1L;

    @TableId(value = "pid", type = IdType.AUTO)
    private String id;

    private String taskId;

    private String userTp;


    private String userId;


    private Integer delFlg;

    private String listType;
}

dao层

@Mapper
public interface ConfUserMapper extends BaseMapper<ConfUser> {
}

业务层

public interface ConfUserService extends IService<ConfUser> {
}
@Service
public class ConfUserServiceImpl extends ServiceImpl<ConfUserMapper, ConfUser> {
}
@Slf4j
@RestController
public class CsvImportController {


    @Resource
    private ConfUserService confUserService;


    @PostMapping("csv")
    public Result csvImport(
            @RequestParam MultipartFile file ){
        System.out.println("进来了====");

        File fileToFile = multipartFileToFile(file);

        CsvReader csvReader = new CsvReader();
        csvReader.setContainsHeader(true);
        CsvContainer csv = null;
        try {
            csv = csvReader.read(fileToFile, StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<ConfUser> add = new ArrayList();
        for (CsvRow row : csv.getRows()) {
            //通过头获取对应属性
            String str=row.getField("userid");
            System.out.println("str  ==="+str);
            ConfUser conf = new ConfUser();

            conf.setDelFlg(0);
            conf.setListType("01");
            conf.setUserId(str);
            conf.setUserTp("01");
            conf.setTaskId("20220906");

            add.add(conf);
        }

        confUserService.saveBatch(add);

        return Result.ok(add);
    }

    public static File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        if (StringUtils.isEmpty(fileName)) {
            return null;
        }
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            log.error("MultipartFile转换为File转换异常:" + e.getMessage());
        }
        return null;
    }

}

大文件csv导入

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j18-impl</artifactId>
            <version>2.18.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.biyanwen</groupId>
            <artifactId>easycsv</artifactId>
            <version>1.0.0</version>
     <!--       <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>-->
        </dependency>

springboot 启动类

public class Application {
	public static ConfigurableApplicationContext ac;
    public static void main(String[] args) {
        ClassPool classPool = ClassPool.getDefault();
        //将当前ClassLoader添加到ClassPath
        classPool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
        ac = SpringApplication.run(SopStoryApplication.class, args);
    }
}

读取工具类 业务逻辑删除了根据自己需要 去增加修改

public class CsvParser extends AbstractCsvFileParser<ConfUserOutputBean> {
    /**
     * 每隔3000条存储数据库,然后清理list ,方便内存回收
     */
    public static final int BATCH_COUNT =10000;
    public int count= 0;

    private String uuid =null;

    private ConfUserService confUserService = ac.getBean(ConfUserService.class);

   


    /**
     * 缓存的数据
     */
    private List<ConfUser> cachedData = new ArrayList<>(BATCH_COUNT);
    private ConfUser confUser;

    public CsvParser(ConfUser confUser, String id, File file) {
        System.out.println("count ==="+count);
        

    }
    /**
     * 所有数据解析完成了 会来调用,防止有数据没有被保存
     *
     */
    @Override
    protected void doAfterAllAnalysed() {
 			
    }
    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    protected void invoke(ConfUserOutputBean confUserOutputBean) {
     
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        confUserService.batchInsert(cachedData,this.confUser,this.uuid);
    }

    public static File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        if (StringUtils.isEmpty(fileName)) {
            return null;
        }
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        System.out.println("prfix==="+prefix);
        if (prefix.equals(".csv")){
            try {
                File file = File.createTempFile(fileName, prefix);
                multiFile.transferTo(file);
                return file;
            } catch (Exception e) {
                System.out.println("MultipartFile转换为File转换异常:" + e.getMessage());
            }
        }
        return null;
    }
}

读取大文件csv行数

    public int countRows(File file){
        int lines =0;
        long times = System.currentTimeMillis();
        if (file.exists()){
            try {
                long length = file.length();
                LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(file));
                lineNumberReader.skip(length);
                lines=lineNumberReader.getLineNumber();
                lineNumberReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
        long end = System.currentTimeMillis();
        System.out.println("lines 总行数为:"+lines);
        return lines;
    }

controller 层

   @PostMapping("csv")
    public Result csvImport(ConfUserVo confUser){
        System.out.println("进来了===="+confUser);

        System.out.println("file ==="+confUser.getFile());
        File file = multipartFileToFile(confUser.getFile());
        if (file==null){
            return Result.error("请上传正确的csv文件");
        }
        System.out.println("file path "+file.getPath());
        String  uuid = IdUtil.simpleUUID();
        int rows = countRows(file)-1;
        // 异步调用
        confUserService.batchAdd(confUser,file,uuid,false);
        JSONObject json =new JSONObject();
        json.putOpt("uuid",uuid);
        json.putOpt("rows",rows);
        return Result.ok(json).setMsg("开始导入");
    }

service层

    @Async
    @Override
    public void batchAdd(ConfUserVo confUser,File file,String uuid, boolean isClose) {
        ConfUser user = new ConfUser();
        user.setUserTp(confUser.getUserTp());
        user.setDelFlg(0);
        user.setListType(confUser.getListType());
        user.setTaskId(confUser.getTaskId());
        //调用工具类读取文件
        EasyCsv.read(file.getPath(), ConfUserOutputBean.class, new CsvParser(user,uuid,file))
                .doRead();
    }

批量新增使用 mybatisplus的批量新增方法

    @Transactional
    @Override
    public void batchInsert( List<ConfUser> add,ConfUser confUser,String uuid) {
        System.out.println("开始新增=====");
        boolean b = this.saveBatch(add);
        System.out.println("b ==="+b);

}
        

在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

௸྄ིོུ倾心ღ᭄ᝰꫛꫀꪝ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值