高效讀取百萬級數據
接上一篇介紹的高效寫文件之后,最近抽時間研究了下Excel文件的讀取。概括來講,poi讀取excel有兩種方式:用戶模式和事件模式。
然而很多業務場景中的讀取Excel仍然采用用戶模式,但是這種模式需要創建大量對象,對大文件的支持非常不友好,非常容易OOM。但是對於事件模式而言,往往需要自己實現listener,並且需要根據自己需要解析不同的event,所以用起來比較復雜。
基於此,EasyExcel封裝了常用的Excel格式文檔的事件解析,並且提供了接口供開發小哥擴展定制化,實現讓你解析Excel不再費神的目的。
Talk is cheap, show me the code.
使用姿勢
pom
<groupId>com.github.Dorae132</groupId>
<artifactId>easyutil.easyexcel</artifactId>
<version>1.1.0</version>
普通姿勢
看看下邊的姿勢,是不是覺得只需要關心業務邏輯了?
ExcelUtils.excelRead(ExcelProperties.produceReadProperties("C:\\Users\\Dorae\\Desktop\\ttt\\",
"append_0745704108fa42ffb656aef983229955.xlsx"), new IRowConsumer<String>() {
@Override
public void consume(List<String> row) {
System.out.println(row);
count.incrementAndGet();
try {
TimeUnit.MICROSECONDS.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, new IReadDoneCallBack<Void>() {
@Override
public Void call() {
System.out.println(
"end, count: " + count.get() + "\ntime: " + (System.currentTimeMillis() - start));
return null;
}
}, 3, true);
定制姿勢
什么?你想定制context,添加handler?請看下邊!你只需要實現一個Abstract03RecordHandler然后regist到context(關注ExcelVersionEnums中的factory)就可以了。
public static void excelRead(IHandlerContext context, IRowConsumer rowConsumer, IReadDoneCallBack callBack,
int threadCount, boolean syncCurrentThread) throws Exception {
// synchronized main thread
CyclicBarrier cyclicBarrier = null;
threadCount = syncCurrentThread ? ++threadCount : threadCount;
if (callBack != null) {
cyclicBarrier = new CyclicBarrier(threadCount, () -> {
callBack.call();
});
} else {
cyclicBarrier = new CyclicBarrier(threadCount);
}
for (int i = 0; i < threadCount; i++) {
THREADPOOL.execute(new ConsumeRowThread(context, rowConsumer, cyclicBarrier));
}
context.process();
if (syncCurrentThread) {
cyclicBarrier.await();
}
}
框架結構
如圖,為整個EasyExcel的結構,其中(如果了解過設計模式,或者讀過相關源碼,應該會很容易理解):
- 綠色為可擴展接口,
- 上半部分為寫文件部分,下辦部分為讀文件。
總結
至此,EasyExcel的基本功能算是晚上了,歡迎各路大神提Issue過來。🍗