JAVA中opencsv包解析CSV大文件 您所在的位置:网站首页 eclipse添加头文件路径 JAVA中opencsv包解析CSV大文件

JAVA中opencsv包解析CSV大文件

2023-05-31 03:38| 来源: 网络整理| 查看: 265

业务的诞生

最近有些从大数据部门下载的基础数据,并已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包

com.opencsv opencsv 5.4

2.创建CsvUtils工具类

@Slf4j public class CsvUtils { private static final String FIELD = "\\w+=(\\-|\\+)?\\d+(\\.\\d+)?"; /** * 解析csv文件并转成bean(方法二) * * @param file csv文件 * @return 数组 */ public static List getCsvDataMethod2(MultipartFile file) { List list = new ArrayList(); int i = 0; try { CSVReader csvReader = new CSVReaderBuilder( new BufferedReader( new InputStreamReader(file.getInputStream(), "utf-8"))).build(); Iterator 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 getCsvDataMethod2Strong(MultipartFile file) { Map resultMap = new HashMap(); // 重新解析数据,将staticsdatamap字段中的数据,解析成各个不同的字段并重新命名中文名称 // 为了避免staticsdatamap中的各个字段数量不同导致表头不统一,先分析出所有的字段,其数据中没有的字段,则补空 List header = new ArrayList(); int staticsdatamapIndex = 0; // 新增的表头字段map Map staticsdatamapAttributeMap = new HashMap(); // 新增的表头字段属性值map Map staticsdatamapAttributeValueMap = new HashMap(); List list = new ArrayList(); int i = 0; try { CSVReader csvReader = new CSVReaderBuilder( new BufferedReader( new InputStreamReader(file.getInputStream(), "utf-8"))).build(); Iterator iterator = csvReader.iterator(); while (iterator.hasNext()) { List 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解析出来的表头字段以及各个数据对应的数值,重新组装成一个新的List for (Map.Entry 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 staticsdatamapAttributeMap, Map staticsdatamapAttributeValueMap, String staticsdatamapValue, int index) { // 正则匹配出所有的字段 Pattern pattern = Pattern.compile(FIELD); Matcher matcher = pattern.matcher(staticsdatamapValue); while (matcher.find()) { // 获取单个匹配项,格式为:spn=value String fieldValue = matcher.group(); // 将单个匹配项拆分成一个list List 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 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 head, List 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 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 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 map = new HashMap(); private static SPNMap spnMap = new SPNMap(); private SPNMap() { } public static SPNMap getInstance(){ return spnMap; } public static Map 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 { @Autowired private 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 resultMap = CsvUtils.getCsvDataMethod2Strong(file); log.info("获取CSV文件中的所有表头"); List header = (List) resultMap.get("header"); log.info("获取CSV文件中的所有数据"); List data = (List) resultMap.get("data"); log.info("导出新的CSV文件"); CsvUtils.createCSVFile(header, data, DIR, file.getOriginalFilename().split("\\.")[0]); log.info("importCSV --- END"); } }

 7.postman调用。。。

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

        



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有