Java实现从本地读取CSV文件数据

一、前言
最近项目中需要实现这样一个功能,就是从本地读取CSV文件,并以指定行作为标题行,指定行开始作为数据读取行,读取数据并返回给前端,下面具体说下是如何通过java实现。

二、如何实现?
1.引入相关maven依赖

<dependency>
       <groupId>cn.hutool</groupId>
       <artifactId>hutool-all</artifactId>
</dependency>

2.定义一个工具类CsvUtils。

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.text.csv.CsvData;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.text.csv.CsvUtil;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class CsvUtils {
	public static final String FIELD_NAME="column";
    public static List<Map<String, Object>> getCsvFileContent(InputStream in, Long readLine, int headerRowIndex, int readCount,String splitChar) throws IOException {
        InputStreamReader is = null;
        CsvReader reader =null;
        InputStream bufferedInputStreamOne =null;
        InputStream bufferedInputStreamTwo =null;
        ByteArrayOutputStream baos =null;
        try {
            if (in == null) {
                throw new FileStorageRuntimeException("文件读取失败,文件不存在!");
            }
            if (readLine ==null){
                readLine =2l;
            }
            List<Map<String, Object>> resList = new ArrayList<>();
            reader = CsvUtil.getReader();
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024*10];
            int len;
            while ((len = in.read(buffer)) > -1 ) {
                baos.write(buffer, 0, len);
            }
            baos.flush();

            bufferedInputStreamOne=new ByteArrayInputStream(baos.toByteArray());
            bufferedInputStreamTwo=new ByteArrayInputStream(baos.toByteArray());
            boolean isUtf8=checkUTF8(bufferedInputStreamOne);
            //从文件中读取CSV数据
            is = new InputStreamReader(bufferedInputStreamTwo,Charset.forName(isUtf8 ? "UTF-8":"GBK"));
            reader.setFieldSeparator(splitChar.charAt(0));
            reader.setSkipEmptyRows(false);
            CsvData data = reader.read(is);
            List<CsvRow> rows = data.getRows();
            //空表格;
            if (rows.isEmpty()) {
                return null;
            }
            List<String> headRowList =new ArrayList<>();
            if (headerRowIndex > 0 && rows.size()>headerRowIndex - 1){
                //获取表头;
                headRowList = rows.get(headerRowIndex - 1).getRawList();
            }else {
                if (CollectionUtil.isNotEmpty(rows)){
                    List<String> rowList=rows.get(0).getRawList();
                    for(int i=1;i<=rowList.size();i++) {
                        headRowList.add(FIELD_NAME+i);
                    }
                }
            }
            List<String> headList=new ArrayList<>();

            for (int i=0;i<headRowList.size();i++) {
                String fieldName = headRowList.get(i);
                if (StrUtil.isBlank(fieldName )) {
                	headList.add(FIELD_NAME+(i+1));
                }else {
                	headList.add(fieldName);
                }
            }
            if (CollUtil.isNotEmpty(rows)){
                CsvRow currCsvRow = rows.get(0);
                if (headList.size() != currCsvRow.getRawList().size()) {
                    throw new FileStorageRuntimeException("列数量与数据数量不一致");
                }
            }
            if (readLine>1) {
                //加上一行
                List<String> addRawListNew = headRowList.stream().map(s -> StrUtil.trim(s)).collect(Collectors.toList());
                Map map = IterUtil.toMap(headList, (Iterable) addRawListNew,true);
                resList.add(map);
            }
            //遍历行
            for (int i = (int)((long)readLine)-1; i < rows.size(); i++) {
                CsvRow csvRow = rows.get(i);
                //getRawList返回一个List列表,列表的每一项为CSV中的一个单元格(既逗号分隔部分)
                List<String> rawList = csvRow.getRawList();
                List<String> rawListNew = rawList.stream().map(s -> StrUtil.trim(s)).collect(Collectors.toList());

                Map map = IterUtil.toMap(headList, (Iterable) rawListNew,true);
                resList.add(map);
                if(readCount>=0 && i>=readCount){
                    break;
                }
            }
            return resList;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("get inputStreamReader failed");
       } finally {
            if (in!=null){
                in.close();
            }
            if (is!=null){
                is.close();
            }
            if (reader!=null){
                reader.close();
            }
            if(bufferedInputStreamTwo !=null){
                bufferedInputStreamTwo.close();
            }
            if(bufferedInputStreamOne !=null){
                bufferedInputStreamOne.close();
            }
            if (baos!=null){
                baos.close();
            }
        }

    }
     /**
     * 判断文件内容是否为 UTF-8 编码
     * @author
     */
    public static boolean checkUTF8(InputStream fis) {
        //请注意fis是流,是不能复用的!
        try {
            while (true) {
                int curr = fis.read();
                if (curr == -1) {
                    return true;
                }
                if (curr < 0x80) {// (10000000): 值小于0x80的为ASCII字符
                } else if (curr < (0xC0)) { // (11000000): 值介于0x80与0xC0之间的为无效UTF-8字符
                    return false;
                } else if (curr < (0xE0)) { // (11100000): 此范围内为2字节UTF-8字符
                    if ((fis.read() & (0xC0)) != 0x80) {
                        return false;
                    }
                    return true;
                } else if (curr < (0xF0)) { // (11110000): 此范围内为3字节UTF-8字符
                    if ((fis.read() & (0xC0)) != 0x80 || (fis.read() & (0xC0)) != 0x80) {
                        return false;
                    }
                    return true;
                } else {
                    return false;
                }
            }
        } catch (IOException e) {
            return true;
        }
    }
    
}

接着通过main方法调用下。

   public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream(new File("D:\\111.csv"));

        List<Map<String, Object>> list=getCsvFileContent(inputStream,2l,1,50,",");
        System.err.println(list);
  }

结果如下:
在这里插入图片描述
其中readCount表示返回的数据数量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/443632.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

西门子PLC中的程序块及类别详解

在PLC的编程中&#xff0c;程序块是指一组逻辑控制代码&#xff0c;用于实现系统中特定的控制功能。程序块主要分为四类&#xff0c;包括函数块&#xff08;FB&#xff09;、函数&#xff08;FC&#xff09;、数据块&#xff08;DB&#xff09;和组织块&#xff08;OB&#xff…

git讲本地代码提交到码云https://gitee.com/

首先需要在码云中自己账号下创建一个空的仓库 第一步 如下图 第二步 仓库名字和仓库是否私有&#xff0c;其他不用选 以上操作好了以后 回到本地&#xff0c;在本地你要上传到仓库的项目路径下&#xff0c;初始化为git 执行 git init 接着&#xff0c;把远程仓库地址复制下…

软件设计师软考题目解析24 --每日五题

想说的话&#xff1a;要准备软考了。0.0&#xff0c;其实我是不想考的&#xff0c;但是吧&#xff0c;由于本人已经学完所有知识了&#xff0c;只是被学校的课程给锁在那里了&#xff0c;不然早找工作去了。寻思着反正也无聊&#xff0c;就考个证玩玩。 本人github地址&#xf…

云原生构建 微服务、容器化与容器编排

第1章 何为云原生&#xff0c;云原生为何而生 SOA也就是面向服务的架构 软件架构的发展主要经历了集中式架构、分布式架构以及云原生架构这几代架构的发展。 微服务架构&#xff0c;其实是SOA的另外一种实现方式&#xff0c;属于SOA的子集。 在微服务架构下&#xff0c;系统…

光明网发布稿件多少钱?新闻投稿低价渠道推荐,附光明网价格明细表

想要在光明网发稿&#xff1f;不知道费用是多少&#xff1f;媒介多多告诉你答案&#xff01; 在当今数字化时代&#xff0c;媒体平台的重要性日益突出&#xff0c;而光明网作为国内知名的新闻门户网站&#xff0c;吸引了大量的目标受众。许多企业和个人都希望能够在光明网上投…

攻防世界——elrond32

运行得到Access deny 我第一次尝试是 修改判断条件&#xff0c;jz改为jnz&#xff0c;jle改为jg&#xff0c; 这个思路运行后&#xff0c;代码因为缺少一个输入&#xff0c;而导致程序运行错误&#xff0c;所以我们只能静态分析 我们想进入Access grant 有两个函数&#xf…

SpringCloudGateway全局过滤器

文章目录 全局过滤器的作用自定义全局过滤器过滤器执行的顺序 上一篇 Gateway理论与实践 介绍的过滤器&#xff0c;网关提供了31种&#xff0c;但每一种过滤器的作用都是固定的。如果我们希望拦截请求&#xff0c;做自己的业务逻辑则没办法实现。 全局过滤器的作用 全局过滤器的…

【Web】浅聊Java反序列化之Rome——关于其他利用链

目录 前言 JdbcRowSetImpl利用链 BasicDataSource利用链 Hashtable利用链 BadAttributeValueExpException利用链 HotSwappableTargetSource利用链 前文&#xff1a;【Web】浅聊Java反序列化之Rome——EqualsBean&ObjectBean-CSDN博客 前言 Rome中ToStringBean的利用…

《Python源码剖析》之字符串拼接的一个效率问题

前言 我们常用的字符串拼接方法有两个&#xff0c;一个是通过“”号实现字符串的拼接&#xff0c;还一个就是通过join方法来实现拼接&#xff0c;前者在写法上更加便利&#xff0c;和数字之间的加法运算一样&#xff0c;通常只有两个运算对象&#xff0c;只不过他们的运算规则…

每日学习笔记:C++ STL 的Array

Array定义 Array模板有两个参数&#xff0c;一个是元素类型&#xff0c;一个是数组大小 Array初始化 Array的操作 Array当作C数组 Array的Tuple接口

搜维尔科技:捕获、分析、优化,使用 Xsens Ergo 创建更安全的工作空间

简化人体工程学分析&#xff0c;优先考虑员工福祉&#xff0c;并利用客观数据和见解提高生产力。 捕获。分析。优化。使用 Xsens Ergo 创建更安全的工作空间 1.质量数据 使用高质量、客观且经过验证的运动数据进行详细的人体工程学分析 2.随处使用 在最具挑战性的工作环境中…

黑马点评-异步秒杀实现

异步秒杀思路 我们来回顾一下下单流程 当用户发起请求&#xff0c;此时会请求nginx&#xff0c;nginx会访问到tomcat&#xff0c;而tomcat中的程序&#xff0c;会进行串行操作&#xff0c;分成如下几个步骤 1、查询优惠卷 2、判断秒杀库存是否足够 3、查询订单 4、校验是…

数据库的筛选条件

【一】筛选过滤条件 【1】完整的查询语句 -- 查询当前表中的全部数据select * from 表名 where 筛选条件;​-- 查询当前表中的指定字段的数据select 字段名,字段名 from 表名 where 筛选条件;# 执行顺序from where select ​select 你选择的列1, 你选择的列2, ... from 查询的…

UE5.1_使用技巧(常更)

UE5.1_使用技巧&#xff08;常更&#xff09; 1. 清除所有断点 运行时忘记蓝图中的断点可能会出现运行错误的可能&#xff0c;务必运行是排除一切断点&#xff0c;逐个排查也是办法&#xff0c;但是在事件函数多的情况下会很复杂且慢节奏&#xff0c;学会一次性清除所有很有必…

Vision Transformer 代码实现

论文链接&#xff1a;An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 最近开始恶补CV了&#xff08;指->新建文件夹&#xff09;。作为CV Transformer的开山大作&#xff0c;首先要学习的就是ViT&#xff08;Vision Transformer&#xff09;…

2024年3月10日 十二生肖 今日运势

小运播报&#xff1a;2024年3月10日&#xff0c;星期日&#xff0c;农历二月初一 &#xff08;甲辰年丁卯月癸酉日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;龙、牛、蛇 需要注意&#xff1a;鸡、狗、兔 喜神方位&#xff1a;东南方 财神方位&#xff1a;…

oracle报错(ORA-06575: 程序包或函数 WM_CONCAT 处于无效状态)

之前的项目突然出现一个错误,ORA-06575: 程序包或函数 WM_CONCAT 处于无效状态 对应的sql如下 SELECT u.LOGIN_NAME,u.REAL_NAME,u.ID,wm_concat(u.ORG_ID) AS ORG_ID,wm_concat(u.ORG_NAME) AS ORG_NAME,wm_concat(u.ORG_CODE) AS ORG_CODE,u.SEX,u.PHONE,u.EMAIL,u.AVATAR…

计算两帧雷达数据之间的变换矩阵

文章目录 package.xmlCMakeLists.txtpoint_cloud_registration.cc运行结果 package.xml <?xml version"1.0"?> <package format"2"><name>point_cloud_registration</name><version>0.0.0</version><descriptio…

Dbeaver:Ubuntu Linux 20.04 mysql 驱动损坏或者没有驱动,无法联网更新下载

下载方法&#xff1a; https://blog.csdn.net/wangpaiblog/article/details/112057533 Ubuntu Linux 20.04 (Architecture Independent), DEB Package 下载地址&#xff1a; https://downloads.mysql.com/archives/c-j/ 安装deb&#xff1a; sudo dpkg -i mysql-connector-java…

存储引擎的简介

简介&#xff1a; 1.在mysql存储引擎可以说就是指表的类型&#xff0c;可以称为表处理器&#xff0c;以表的形式存储。 2.他的功能就是接收上层传下来的指令&#xff0c;然后对表中的数据进行提取写入操作。 目的&#xff1a; 为了管理方便&#xff0c;我们把连接管理&#xf…