zoukankan      html  css  js  c++  java
  • java批量读取多个文件并存入数据库

    背景:有时候服务运行的日志文件,需要统计分析,但数据量很大,并且直接在文件中看很不直观,这时可以将文件中的内容导入到数据库,入库后的数据就可以按照需求进行统计分析了。

    这个是以服务器的访问日志作为示例,一个日志文件中一行的数据格式如下(文件夹中有多个日志文件):

    [10/Aug/2018:00:47:39 +0800] ******* - 356 "-" "GET https://****/****/image57.png" 200 0 5510 HIT "******" "image/png"

    下面就是具体的读取文件,然后插入到数据库的过程,代码如图:

    package com.mobile.web.api;
    
    import com.mobile.commons.JsonResp;
    import com.mobile.model.LogInfo;
    import com.mobile.service.LogInfoService;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.*;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.Locale;
    
    
    @RestController
    @RequestMapping(value = "/test")
    @Transactional
    public class ImportController {
        Logger log = Logger.getLogger(this.getClass());
    
        @Autowired
        private LogInfoService logInfoService;
    
        @RequestMapping(value = "/importTxt", method = RequestMethod.GET)
        public JsonResp importTxt() throws IOException, ParseException {
            log.debug("开始导入数据");
    
            String encoding = "GBK";
            List logInfoList = new ArrayList();
            String dir = "E:\test\log";
            File[] files = new File(dir).listFiles();
            for (File file : files){           //循环文件夹中的文件
                if (file.isFile() && file.exists()) { //判断文件是否存在
                    importFile(file, encoding, logInfoList);  //将文件中的数据读取出来,并存放进集合中
                } else {
                    return JsonResp.toFail("文件不存在,请检查文件位置!");
                }
            }
    
            Boolean insertFlag = logInfoService.insertBatch(logInfoList);   //将集合中的数据批量入库
            if (!insertFlag) {
                return JsonResp.toFail("保存失败");
            }
            return JsonResp.ok();
        }

      /** 读取数据,存入集合中 */
    public static void importFile(File file, String encoding, List logInfoList) throws IOException, ParseException { InputStreamReader read = null;//考虑到编码格式 try { read = new InputStreamReader( new FileInputStream(file), encoding);  //输入流 } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null; SimpleDateFormat sdf = new SimpleDateFormat("[dd/MMM/yyyy:HH:mm:ss Z]", Locale.US); //时间格式化,此处有坑,下边会说到 while ((lineTxt = bufferedReader.readLine()) != null) {  //读取文件内容 String[] lineArr = lineTxt.split(" "); int len = lineArr.length; LogInfo logInfo = new LogInfo();     //封装实体对象做入库准备 String logDate = lineArr[0] + " " + lineArr[1]; System.out.println(sdf.parse(logDate)); //.............时间转换问题 logInfo.setLog1(sdf.parse(logDate)); logInfo.setLog2(lineArr[2]); logInfo.setLog3(lineArr[3]); logInfo.setLog4(lineArr[4]); logInfo.setLog5(lineArr[5].substring(1, lineArr[5].length() - 1)); logInfo.setLog6(lineArr[6].substring(1)); logInfo.setLog8(lineArr[7].substring(0, lineArr[7].length() - 1)); String accessUrl = lineArr[7]; String[] accessUrlArr = accessUrl.split("/"); logInfo.setItemName(accessUrlArr[3]); logInfo.setLog9(lineArr[8]); logInfo.setLog10(lineArr[9]); logInfo.setLog11(lineArr[10]); logInfo.setLog12(lineArr[11]); String[] uaHead = new String[len - 13]; System.arraycopy(lineArr, 12, uaHead, 0, len - 13);//数组拷贝,a表示源数组,b表示源数组要复制的起始位置,c表示目标数组,d表示目标数组起始位置,e表示要复制的长度。 logInfo.setLog13(StringUtils.join(uaHead)); logInfo.setFileType(lineArr[len - 1]); logInfoList.add(logInfo); } read.close(); //输入流关闭 } }

    文件导入,成功;

        log文件夹下的结构如下图:

        

    时间转换时的坑

      SimpleDateFormat sdf = new SimpleDateFormat("[dd/MMM/yyyy:HH:mm:ss Z]", Locale.US);

      字符串转时间时:英文简写为英文格式,而转换时JRE会按照当前地区的语言格式,所以转换失败

      解决方法:带上Locale.US参数

      详细解决可参考:https://www.cnblogs.com/mufengforward/p/9480102.html

    此时,如果数据量特别大时,会出现入库慢的情况,有另一种方法是:读取文件后,将数据按照想要的格式存如新文件中,然后用sql语句(或navicat客户端)导入文件;

       

    www.feng16.com

  • 相关阅读:
    React—ref 属性
    【支付宝SDK】沙箱调试,以及遇到的坑
    python 字符串相乘
    微信小程序授权获取手机号 出现-41003错误
    微信小程序 动态添加 view input picker
    PHP 获取当月的第一天和最后一天
    微信小程序 弹窗组件
    微信小程序 图片等比例 适应屏幕尺寸
    微信小程序图片预览
    div背景图占满
  • 原文地址:https://www.cnblogs.com/mufengforward/p/9482996.html
Copyright © 2011-2022 走看看