大きなファイルを読み込んでみたくて、前回のサンプルをベースに、むりやりファイルを読み込む処理を付け足して、大きめのサイズ(48MB 強)の HTML のテーブルを読み込ませてみました。
例に示した読み込むファイルの拡張子は、.xls になっていますが、中身は HTML です。ただし、読み込む形式が判っているので、汎用のパーサーを用いずに、一行ずつ読み込んで専用の処理をしています。このファイルはあるシステムが吐き出すログなのですが、詳細な説明は割愛します。
List: NatTableSample002.java
/*******************************************************************************
* Copyright (c) 2012 Original authors and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Original authors and others - initial API and implementation
******************************************************************************/
// modified by Fuhito Suguri, 9-Sep-2014
package nattablesample;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
public class NatTableSample002 extends ApplicationWindow {
private IDataProvider bodyDataProvider;
private BodyLayerStack bodyLayer;
private String[] propertyNames;
private Map<String, String> propertyToLabels;
public NatTableSample002() {
super(null);
}
@Override
protected Control createContents(Composite parent) {
parent.setSize(400, 200);
FillLayout layout = new FillLayout(SWT.HORIZONTAL | SWT.VERTICAL);
// Body Layer
bodyDataProvider = setupBodyDataProvider();
bodyLayer = new BodyLayerStack(bodyDataProvider);
// Column Layer
DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabels);
ColumnHeaderLayerStack columnHeaderLayer = new ColumnHeaderLayerStack(colHeaderDataProvider);
// Row Layer
DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
RowHeaderLayerStack rowHeaderLayer = new RowHeaderLayerStack(rowHeaderDataProvider);
// Corner Layer
DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(colHeaderDataProvider, rowHeaderDataProvider);
CornerLayer cornerLayer = new CornerLayer(new DataLayer(cornerDataProvider), rowHeaderLayer, columnHeaderLayer);
// Grid Layer
GridLayer gridLayer = new GridLayer(bodyLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer);
NatTable natTable = new NatTable(parent, gridLayer);
natTable.setLayout(layout);
return natTable;
}
// setupBodyDataProvider
private IDataProvider setupBodyDataProvider() {
String fileName = "/home/bitwalk/ドキュメント/myExcel.xls";
propertyToLabels = new HashMap<String, String>();
propertyToLabels.put("lictype", "ライセンス タイプ");
propertyToLabels.put("monthdate", "月の日");
propertyToLabels.put("userid", "ユーザーID");
propertyToLabels.put("site", "サイト");
propertyToLabels.put("available", "アベイラビリティ");
propertyToLabels.put("percentused", "パーセント使用");
propertyToLabels.put("start", "開始");
propertyToLabels.put("end", "終了");
propertyNames = new String[] { "lictype", "monthdate", "userid", "site", "available", "percentused", "start", "end" };
List<LicData> licUsage = new ArrayList<LicData>();
try {
File file = new File(fileName);
if (checkBeforeReadfile(file)) {
BufferedReader br = new BufferedReader(new FileReader(file));
String str;
String[] elem = new String[8];
int counter = 0;
while ((str = br.readLine()) != null) {
String line = str.trim();
if (line.length() == 0) {
continue;
}
if (line.equals("<tr>")) {
counter = 0;
continue;
}
if (line.equals("</tr>")) {
licUsage.add(new LicData(elem[0], elem[1], elem[2], elem[3], elem[4], elem[5], elem[6], elem[7]));
continue;
}
if (line.startsWith("<td>")) {
int lLength = line.length();
elem[counter] = new String(line.substring(4,
lLength - 5));
counter++;
}
}
br.close();
} else {
System.out.println("Can not find or can not open the file!");
}
} catch (FileNotFoundException e) {
System.out.println(e);
} catch (IOException e) {
System.out.println(e);
}
return new ListDataProvider<LicData>(licUsage, new ReflectiveColumnPropertyAccessor<LicData>(propertyNames));
}
private static boolean checkBeforeReadfile(File file) {
if (file.exists()) {
if (file.isFile() && file.canRead()) {
return true;
}
}
return false;
}
// row structure of license usage data
public class LicData {
private String lictype;
private String monthdate;
private String userid;
private String site;
private String available;
private String percentused;
private String start;
private String end;
public LicData(String lictype, String monthdate, String userid,
String site, String available, String percentused,
String start, String end) {
this.lictype = lictype;
this.monthdate = monthdate;
this.userid = userid;
this.site = site;
this.available = available;
this.percentused = percentused;
this.start = start;
this.end = end;
}
public String getLictype() {
return lictype;
}
public String getMonthdate() {
return monthdate;
}
public String getUserid() {
return userid;
}
public String getSite() {
return site;
}
public String getAvailable() {
return available;
}
public String getPercentused() {
return percentused;
}
public String getStart() {
return start;
}
public String getEnd() {
return end;
}
}
// class BodyLayerStack
public class BodyLayerStack extends AbstractLayerTransform {
private SelectionLayer selectionLayer;
public BodyLayerStack(IDataProvider dataProvider) {
DataLayer bodyDataLayer = new DataLayer(dataProvider);
ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
selectionLayer = new SelectionLayer(columnHideShowLayer);
ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
setUnderlyingLayer(viewportLayer);
}
public SelectionLayer getSelectionLayer() {
return selectionLayer;
}
}
// class ColumnHeaderLayerStack
public class ColumnHeaderLayerStack extends AbstractLayerTransform {
public ColumnHeaderLayerStack(IDataProvider dataProvider) {
DataLayer dataLayer = new DataLayer(dataProvider);
ColumnHeaderLayer colHeaderLayer = new ColumnHeaderLayer(dataLayer, bodyLayer, bodyLayer.getSelectionLayer());
setUnderlyingLayer(colHeaderLayer);
}
}
// class RowHeaderLayerStack
public class RowHeaderLayerStack extends AbstractLayerTransform {
public RowHeaderLayerStack(IDataProvider dataProvider) {
DataLayer dataLayer = new DataLayer(dataProvider, 100, 20);
RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(dataLayer, bodyLayer, bodyLayer.getSelectionLayer());
setUnderlyingLayer(rowHeaderLayer);
}
}
public static void main(String[] args) {
NatTableSample002 w = new NatTableSample002();
w.setBlockOnOpen(true);
w.open();
Display.getCurrent().dispose();
}
}
実行例
79,446 行というのは、Excel で扱えない行数では決してありませんが、こんなに簡単に読み込めるんだということでオドロキです。もっとも読み込み速度が速いのは、単純にファイルの読み込み処理を特化しているせいなのでしょう。
定型のデータを読み込ませる場合は、このようなやり方で良いのですが、汎用目的に読み込むためにどうするのか、調べる必要があります。
参考サイト
- テキストファイルを読む - テキストファイルの入出力 - Java入門