业务的诞生

最近有些从大数据部门下载的基础数据,并已csv格式存储的,其中一些单个文件中数据量达到200W条。现在需要我把文件重新解析一次。因为其中一个表头对应的值是一个{key1=value1, key2=value2,key3=value3}类型。因为key的值都是定义的码值,所以要把key1、key2、key3等解析出来并翻译成对应的中文名称作为新的表头,然后生成新的csv文件。

优先思考解决思路

1.用Excel打开csv文件最大能展示出1048576行,想让领导能看到所有数据,当然需要拆分文件哦

2.我是将csv拆分成多个且最大900000条数据的csv文件,即便如此,单个文件也达到400M左右,程序处理过程中,要考虑下JVM内存,(我本地跑的程序,Xmx设置成8G),内存太小,肯定会内存溢出的。

3.接下来,当然是要做程序员最爱的事情,写逻辑!!!

csv大文件的拆分

网上找到了一个很好的文件处理工具:Data.olllo

 下载地址:http://olllo.top

操作都是傻瓜式的,就不细说:安装好工具-->打开工具-->打开文件-->拆分文件

代码实现过程

1.导入opencsv包

<!-- csv文件解析依赖 --><dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId><version>5.4</version></dependency>

2.创建CsvUtils工具类

@Slf4j
public class CsvUtils {private static final String FIELD = "\\w+=(\\-|\\+)?\\d+(\\.\\d+)?";/*** 解析csv文件并转成bean(方法二)** @param file csv文件* @return 数组*/public static List<String[]> getCsvDataMethod2(MultipartFile file) {List<String[]> list = new ArrayList<String[]>();int i = 0;try {CSVReader csvReader = new CSVReaderBuilder(new BufferedReader(new InputStreamReader(file.getInputStream(), "utf-8"))).build();Iterator<String[]> iterator = csvReader.iterator();while (iterator.hasNext()) {String[] next = iterator.next();//去除第一行的表头,从第二行开始//if (i >= 1) {}list.add(next);i++;}return list;} catch (Exception e) {System.out.println("CSV文件读取异常");return list;}}/*** 解析csv文件并转成bean(方法二) 方法的增强,解析某个表头字段(数据是多个key-value),分离成新的多个字段** @param file csv文件* @return 数组*/public static Map<String, Object> getCsvDataMethod2Strong(MultipartFile file) {Map<String, Object> resultMap = new HashMap<>();// 重新解析数据,将staticsdatamap字段中的数据,解析成各个不同的字段并重新命名中文名称// 为了避免staticsdatamap中的各个字段数量不同导致表头不统一,先分析出所有的字段,其数据中没有的字段,则补空List<String> header = new ArrayList<>();int staticsdatamapIndex = 0;// 新增的表头字段mapMap<String, String> staticsdatamapAttributeMap = new HashMap<>();// 新增的表头字段属性值mapMap<Integer, Map<String, String>> staticsdatamapAttributeValueMap = new HashMap<>();List<List<String>> list = new ArrayList<>();int i = 0;try {CSVReader csvReader = new CSVReaderBuilder(new BufferedReader(new InputStreamReader(file.getInputStream(), "utf-8"))).build();Iterator<String[]> iterator = csvReader.iterator();while (iterator.hasNext()) {List<String> next = new ArrayList(Arrays.asList(iterator.next()));//第一行的表头,数据从第二行开始if (i == 0) {header = next;// 分析表头字段是staticsdatamap的下标值for (int j = 0; j < header.size(); j++) {if ("staticsdatamap".equals(header.get(j))) {staticsdatamapIndex = j;}}} else {// 获取staticsdatamap字段对应的值String staticsdatamapValue = next.get(staticsdatamapIndex);// 解析staticsdatamap字段对应的值,分析出各个字段值analysisMap(staticsdatamapAttributeMap, staticsdatamapAttributeValueMap, staticsdatamapValue, i - 1);list.add(next);log.info("解析完第 {} 条数据", i);}i++;}// 根据staticsdatamap解析出来的表头字段以及各个数据对应的数值,重新组装成一个新的Listfor (Map.Entry<String, String> entry : staticsdatamapAttributeMap.entrySet()) {header.add(entry.getValue());for (int j = 0; j < list.size(); j++) {if (staticsdatamapAttributeValueMap.containsKey(j)) {list.get(j).add(staticsdatamapAttributeValueMap.get(j).get(entry.getKey()));} else {list.get(j).add("");}}}resultMap.put("header", header);resultMap.put("data", list);return resultMap;} catch (Exception e) {System.out.println("CSV文件读取异常");return resultMap;}}private static void analysisMap(Map<String, String> staticsdatamapAttributeMap,Map<Integer, Map<String, String>> staticsdatamapAttributeValueMap,String staticsdatamapValue,int index) {// 正则匹配出所有的字段Pattern pattern = Pattern.compile(FIELD);Matcher matcher = pattern.matcher(staticsdatamapValue);while (matcher.find()) {// 获取单个匹配项,格式为:spn=valueString fieldValue = matcher.group();// 将单个匹配项拆分成一个listList<String> keyAndValueList = Arrays.asList(fieldValue.split("="));// 从SPNMap中查找中文对照关系,如果找到了,则重新创建新的表头字段名: 中文名(SPN),如果没有,则剔除数据if (SPNMap.getInstance().getMap().containsKey(keyAndValueList.get(0))) {String newFieldName = SPNMap.getInstance().getMap().get(keyAndValueList.get(0)) + "(" + keyAndValueList.get(0) + ")";staticsdatamapAttributeMap.put(keyAndValueList.get(0), newFieldName);if (CollectionUtils.isEmpty(staticsdatamapAttributeValueMap.get(index))) {Map<String, String> tempMap = new HashMap<>();tempMap.put(keyAndValueList.get(0), keyAndValueList.get(1));staticsdatamapAttributeValueMap.put(index, tempMap);} else {staticsdatamapAttributeValueMap.get(index).put(keyAndValueList.get(0), keyAndValueList.get(1));}}}}/*** CSV文件生成方法* @param head 文件头* @param dataList 数据列表* @param outPutPath 文件输出路径* @param filename 文件名* @return*/public static File createCSVFile(List<Object> head, List<List<Object>> dataList,String outPutPath, String filename) {File csvFile = null;BufferedWriter csvWtriter = null;try {csvFile = new File(outPutPath + File.separator + filename + ".csv");File parent = csvFile.getParentFile();if (parent != null && !parent.exists()) {parent.mkdirs();}csvFile.createNewFile();// GB2312使正确读取分隔符","csvWtriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "GBK"), 1024);// 写入文件头部writeRow(head, csvWtriter);int i = 0;// 写入文件内容for (List<Object> row : dataList) {writeRow(row, csvWtriter);i ++;log.info("成功写入CSV第 {} 条数据", i);}csvWtriter.flush();} catch (Exception e) {e.printStackTrace();} finally {try {csvWtriter.close();} catch (IOException e) {e.printStackTrace();}}return csvFile;}/*** 写一行数据方法* @param row* @param csvWriter* @throws IOException*/private static void writeRow(List<Object> row, BufferedWriter csvWriter) throws IOException {// 写入文件头部for (Object data : row) {StringBuffer sb = new StringBuffer();String rowStr = sb.append("\"").append(data == null ? "" : data).append("\",").toString();csvWriter.write(rowStr);}csvWriter.newLine();}
}

3.创建一个饿汉式单利类初始化常量集合(涉及隐私安全,所以用key1、key2、key3......代替)

public class SPNMap {private static final Map<String, String> map = new HashMap<>();private static SPNMap spnMap = new SPNMap();private SPNMap() {}public static SPNMap getInstance(){return spnMap;}public static Map<String, String> getMap() {return map;}static {map.put("key1", "value1");map.put("key1", "value2");map.put("key1", "value3");map.put("key1", "value4");map.put("key1", "value5");}
}

4.Controller代码

/*** @program com.example.demo.controller* @description 公共* @auther Mr.Xiong* @create 2020-03-07 12:36*/
@RestController
@RequestMapping("/common")
public class CommonController {@Autowiredprivate CommonService commonService;@ResponseBody@RequestMapping("/importCSV")public void importCSV(MultipartFile file) {commonService.importCSV(file);}
}

5.Service

/*** @program com.example.demo.service* @description common service* @auther Mr.Xiong* @create 2020-03-07 13:10*/
@Service
public interface CommonService {void importCSV(MultipartFile file);
}

6.ServiceImpl

/*** @program com.example.demo.service* @description common service* @auther Mr.Xiong* @create 2020-03-07 13:10*/
@Slf4j
@Service
public class CommonServiceImpl implements CommonService {private static final String DIR = "C:\\Users\\50299\\Desktop\\csv";public void importCSV(MultipartFile file) {log.info("importCSV --- START");log.info("获取CSV文件中的所有表头加数据");Map<String, Object> resultMap = CsvUtils.getCsvDataMethod2Strong(file);log.info("获取CSV文件中的所有表头");List<Object> header = (List<Object>) resultMap.get("header");log.info("获取CSV文件中的所有数据");List<List<Object>> data = (List<List<Object>>) resultMap.get("data");log.info("导出新的CSV文件");CsvUtils.createCSVFile(header, data, DIR, file.getOriginalFilename().split("\\.")[0]);log.info("importCSV --- END");}
}

 7.postman调用。。。

8.整个过程,大概用了一天时间。当一切搞定的时候,感觉还挺有成就感!!!

        

JAVA中opencsv包解析CSV大文件相关推荐

  1. Java用数组的包文件_在Java中获取包内的类文件数组

    我能够使用普通的文件I / O和搜索机制来解决这个问题.您可以在此处查看答案. private static List getClassesForPackage(Package pkg) { Stri ...

  2. php如何导入大文件数据库,PHP读取CSV大文件导入数据库的示例

    文章详细介绍了csv文件在php中快速导入到mysql数据库中的例子,虽然从最简单的几百MB的到最后使用插件实现几个GB数据导入中间有一些嗑碰了,但结果还是好的. 对于数百万条数据量的CSV文件,文件 ...

  3. JAVA中利用DOM解析XML文档

    JAVA中利用DOM解析XML文档 package org.sws.utils; import java.io.File;import java.io.IOException; import java ...

  4. php读取csv指定行_PHP快速读取CSV大文件指定行

    1.如何快速获取CSV大文件的总行数? 办法一:直接获取文件内容,使用换行符进行拆分得出总行数,这种办法对小文件可行,处理大文件时不可行: 办法二:使用fgets一行一行遍历,得出总行数,这种办法比办 ...

  5. Php流式 大文件,如何使用PHP解析XML大文件

    如果使用 PHP 解析 XML 的话,那么常见的选择有如下几种:DOM.SimpleXML.XMLReader.如果要解析 XML 大文件的话,那么首先要排除的是 DOM,因为使用 DOM 的话,需要 ...

  6. Java中的包(package)详情解释

    一.Java 包(package) 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间. 包的作用 1.把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用. 2.如同文件夹一 ...

  7. java如何解压rar文件怎么打开_如何在java中实现对zip和rar文件的解压

    如何在java中实现对zip和rar文件的解压 关注:101  答案:1  mip版 解决时间 2021-01-26 10:50 提问者芣①樣哋羙莮 2021-01-25 22:44 如何在java中 ...

  8. Java中jar包怎么使用_java中jar包的使用方法

    java中jar包的使用方法 发布时间:2020-06-23 11:08:05 来源:亿速云 阅读:162 作者:Leah 这篇文章将为大家详细讲解有关java中jar包的使用方法,小编觉得挺实用的, ...

  9. Java 中调用 Apache API 实现图片文件的 压缩 与 解压 实例

    < Java 中调用 Apache API 实现图片文件的 压缩 与 解压 > 为什么不直接使用 Java JDK 中自带的 API 呢?必须使用 Apache API 实现文件的压缩与解 ...

最新文章

  1. screen 常用命令
  2. IP地址的三种表示格式及在Socket编程中的应用
  3. 1.2.2 OSI参考模型
  4. 4.Winform实现控件拖动
  5. 阿里linux安装mysql_阿里云Linux Ubuntu系统安装mysql完整过程
  6. POJ-1556 The Doors 线段相交+最短路
  7. The Power of Android Action Bars(转载)
  8. java多态和泛型_Java面向对象(二) 接口、多态和泛型
  9. 【JEECG 官方】技术支持联系方式
  10. thinkphp-查询某一列的值column
  11. viewpager fragment FragmentStatePagerAdapter数据删除后更新界面
  12. java dayofweek_Java日期时间API系列22-----Jdk8中java.time包中的新的日期时间API类,Month月份和DayOfWeek星期的计算。...
  13. SpringBoot 中解决跨域请求
  14. Android FloatingActionButton(FAB) 悬浮按钮
  15. 人工智能:一种现代的方法|课后习题解答
  16. stm32神舟I号开发板下的六子棋开发
  17. 使用gsds绘制基因结构图_GSDS 基因结构显示系统
  18. 带薪拉屎是一种怎样的体验
  19. 新东方王强的一篇精彩演讲
  20. Linux中ps命令 ps aux与ps -ef的区别

热门文章

  1. springboot 整合javassist详解
  2. JavaScript 加密库 crypto-js
  3. matlab 画折线图(美化)
  4. 最新影视双端最全视频教程+源码
  5. 模块DIY——基于DDS直接数字频率合成技术自制的可编程任意波形发生器模块(DDS原理、寄存器解读、原理图设计、驱动程序-适用于AD9833/AD9834/AD9838)
  6. Tomcat不自动解压war包
  7. Mysql批量插入数据问题解决和优化
  8. NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等
  9. 计算机科学概论英文版第五版答案,计算机科学导论习题答案(Introduction to computer science exercises answer).doc...
  10. win7通过cmd创建wifi热点无需软件