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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM