國產(chǎn)一級a做爰片免費網(wǎng)站哪個網(wǎng)站是免費的
前言
? ? ? 最近有個項目在生產(chǎn)環(huán)境做數(shù)據(jù)導(dǎo)入時,發(fā)現(xiàn)開始執(zhí)行導(dǎo)入任務(wù)會出現(xiàn)cpu狂飆的情況。幾番定位查找發(fā)現(xiàn)是在讀取excel的時候?qū)е麓藛栴}的發(fā)生,因此在通常使用的為POI的普通讀取,在遇到大數(shù)據(jù)量excel,50MB大小或數(shù)五十萬行的級別的數(shù)據(jù)容易導(dǎo)致讀取時內(nèi)存溢出或者cpu飆升。需要注意,本文討論的是針對xlsx格式的excel文件上傳。
關(guān)于Excel相關(guān)技術(shù)
? ? ? ? 在Java技術(shù)生態(tài)圈中,可以進(jìn)行Excel處理的主流技術(shù)包括:Apache POI,JXL,Alibaba EasyExcel等。由于JXL只支持Excel2003以下版本,所以不太常見。
Apache POI:基于DOM方式進(jìn)行解析,將文件直接加載內(nèi)存,所以速度較快,適合Excel文件數(shù)量不大的應(yīng)用場景
Alibaba EasyExcel:采用逐行讀取的解析模式,將每一行的解析結(jié)果以觀察者模式通知處理(AnalyEventListener),所以比較適合數(shù)據(jù)體量較大的Excel文件解析。
問題代碼
? ? ? ?這種方式POI會把文件的所有內(nèi)容都加載到內(nèi)存中,讀取大的excel文件時很容易占用大量內(nèi)存導(dǎo)致oom的發(fā)生,全部文件加載如下:
/*** POI方式讀取excel** @param file*/public static void readExcelByPoi(File file) {long start = System.currentTimeMillis();//整個文件都一塊載入try (InputStream inp = new FileInputStream(file);Workbook wb = WorkbookFactory.create(inp)) {log.info("==讀取excel完畢,耗時:{}毫秒,", System.currentTimeMillis() - start);Sheet sheet = wb.getSheetAt(0);//更新總數(shù)System.out.println("讀取結(jié)束行數(shù):" + sheet.getLastRowNum());} catch (Exception e) {e.printStackTrace();}}
當(dāng)前引入的poi依賴
<!-- excel工具 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.0</version></dependency>
? ? ?讀取50MB我本地字段不是很多50萬行數(shù)據(jù)
首先在讀取excel文件的斷點執(zhí)行之前的cpu和內(nèi)存的占用分別為50%和42%,上傳的excel大小為50MB,這里我就不一一帶大家測試了,以上此種方式肯定是行不通的。
解決方案一:xlsx-streamer
? ? ? 我們采用分段緩存的方式加載數(shù)據(jù)到內(nèi)存中,此種方式在創(chuàng)建Workbook對象時借助xlsx-streamer(StreamingReader) 來創(chuàng)建一個緩沖區(qū)域批量地讀取文件 ,因此不會將整個文件實例化到對象當(dāng)中,代碼如下:
引入依賴:
<!-- excel工具 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.0</version></dependency><!-- 讀取大量excel數(shù)據(jù)時使用 --><dependency><groupId>com.monitorjbl</groupId><artifactId>xlsx-streamer</artifactId><version>2.1.0</version></dependency>
示例代碼:
/*** 大批量數(shù)據(jù)讀取 十萬級以上* 思路:采用分段緩存加載數(shù)據(jù),防止出現(xiàn)OOM的情況** @param file* @throws Exception*/public static void readLagerExcel(File file) throws Exception {InputStream inputStream = new FileInputStream(file);long start = System.currentTimeMillis();try (Workbook workbook = StreamingReader.builder().rowCacheSize(10 * 10) //緩存到內(nèi)存中的行數(shù),默認(rèn)是10.bufferSize(1024 * 4) //讀取資源時,緩存到內(nèi)存的字節(jié)大小,默認(rèn)是1024.open(inputStream)) { //打開資源,可以是InputStream或者是File,注意:只能打開.xlsx格式的文件Sheet sheet = workbook.getSheetAt(0);log.info("==讀取excel完畢,耗時:{}毫秒,", System.currentTimeMillis() - start);//遍歷所有的行for (Row row : sheet) {System.out.println("開始遍歷第" + row.getRowNum() + "行數(shù)據(jù):");//遍歷所有的列for (Cell cell : row) {System.out.print(cell.getStringCellValue() + " ");}System.out.println(" ");}//總數(shù)System.out.println("讀取結(jié)束行數(shù):" + sheet.getLastRowNum());}}
加載結(jié)果
40萬級別數(shù)據(jù)近花費5秒,加載是不是很快了。
百萬級別,也就花費7秒
前端也還做了個測試頁面如下:
Excel文件上傳
解決方案二:EasyExcel
? ? ?使用EasyExcel解決大文件Excel內(nèi)存溢出的問題,基于POI進(jìn)行封裝優(yōu)化,可以在不考慮性能、內(nèi)存的等因素的情況下,快速完成Excel的讀、寫等功能。
官網(wǎng): https://easyexcel.opensource.alibaba.com/
github:https://github.com/alibaba/easyexcel
引入依賴
<!--easyExcel工具--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.1</version></dependency>
示例代碼
僅做簡單讀取示例:
/*** EasyExcel方式讀取excel* 讀取并封裝為對象,ExcelData大家需要的對象* @param file*/public static void readExcelByEasyExcel(File file) {long start = System.currentTimeMillis();List<ExcelData> excelDataList = EasyExcel.read(file).head(ExcelData.class).sheet(0).doReadSync();excelDataList.stream().forEach(x -> System.out.println(x.toString()));log.info("==讀取excel完畢,耗時:{}毫秒,", System.currentTimeMillis() - start);}/*** EasyExcel方式讀取excel* 不指定head類* @param file*/public static void readExcelByEasyExcel1(File file) {long start = System.currentTimeMillis();List<Map<Integer, String>> listMap = EasyExcel.read(file).sheet(0).doReadSync();listMap.stream().forEach(x -> System.out.println(JSON.toJSONString(x)));log.info("==讀取excel完畢,耗時:{}毫秒,", System.currentTimeMillis() - start);}
? ?得出一個結(jié)論就是使用阿里EasyExcel確實方便很多,不僅支持excel,csv也可以。支持的文件類型更多些,但是第一種方式也還可以,畢竟poi我們也一直在使用。