`
javaEdge
  • 浏览: 22264 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java读取大数据量Excel的方法(POI)

    博客分类:
  • java
阅读更多

 工作当中遇到要读取大数据量Excel(10万行以上,Excel 2007),用POI方式读取,用HSSFWorkbook读取时,超过2万行JVM的内存就会溢出,在网上找到原来要用XML方式逐行读取,记录下来,以供参考。

    注意:运行环境是jdk1.6,如果要在1.5的环境中运行,要把jdk1.6中的rt.jar中javax.xml包下所有类加到运行的环境中。

    下面是代码:

package com.bill.excel;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

public class ExcelUtil extends DefaultHandler {
	
	private SharedStringsTable sst;
	private String lastContents;
	private boolean nextIsString;

	private int sheetIndex = -1;
	private List<String> rowlist = new ArrayList<String>();
	private int curRow = 0;
	private int curCol = 0;
	
	
	/**
	 * 读取第一个工作簿的入口方法
	 * @param path
	 */
	public void readOneSheet(String path) throws Exception {
		OPCPackage pkg = OPCPackage.open(path);		
		XSSFReader r = new XSSFReader(pkg);
		SharedStringsTable sst = r.getSharedStringsTable();
			
		XMLReader parser = fetchSheetParser(sst);
			
		InputStream sheet = r.getSheet("rId1");

		InputSource sheetSource = new InputSource(sheet);
		parser.parse(sheetSource);
			
		sheet.close();		
	}
	
	
	/**
	 * 读取所有工作簿的入口方法
	 * @param path
	 * @throws Exception
	 */
	public void process(String path) throws Exception {
		OPCPackage pkg = OPCPackage.open(path);
		XSSFReader r = new XSSFReader(pkg);
		SharedStringsTable sst = r.getSharedStringsTable();

		XMLReader parser = fetchSheetParser(sst);

		Iterator<InputStream> sheets = r.getSheetsData();
		while (sheets.hasNext()) {
			curRow = 0;
			sheetIndex++;
			InputStream sheet = sheets.next();
			InputSource sheetSource = new InputSource(sheet);
			parser.parse(sheetSource);
			sheet.close();
		}
	}
	
	/**
	 * 该方法自动被调用,每读一行调用一次,在方法中写自己的业务逻辑即可
	 * @param sheetIndex 工作簿序号
	 * @param curRow 处理到第几行
	 * @param rowList 当前数据行的数据集合
	 */
	public void optRow(int sheetIndex, int curRow, List<String> rowList) {
		String temp = "";
		for(String str : rowList) {
			temp += str + "_";
		}
		System.out.println(temp);
	}
	
	
	public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
		XMLReader parser = XMLReaderFactory
				.createXMLReader("org.apache.xerces.parsers.SAXParser");
		this.sst = sst;
		parser.setContentHandler(this);
		return parser;
	}
	
	public void startElement(String uri, String localName, String name,
			Attributes attributes) throws SAXException {
		// c => 单元格
		if (name.equals("c")) {
			// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
			String cellType = attributes.getValue("t");
			if (cellType != null && cellType.equals("s")) {
				nextIsString = true;
			} else {
				nextIsString = false;
			}
		}
		// 置空
		lastContents = "";
	}
	
	
	public void endElement(String uri, String localName, String name)
			throws SAXException {
		// 根据SST的索引值的到单元格的真正要存储的字符串
		// 这时characters()方法可能会被调用多次
		if (nextIsString) {
			try {
				int idx = Integer.parseInt(lastContents);
				lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
						.toString();
			} catch (Exception e) {

			}
		}

		// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
		// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
		if (name.equals("v")) {
			String value = lastContents.trim();
			value = value.equals("") ? " " : value;
			rowlist.add(curCol, value);
			curCol++;
		} else {
			// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
			if (name.equals("row")) {
				optRow(sheetIndex, curRow, rowlist);
				rowlist.clear();
				curRow++;
				curCol = 0;
			}
		}
	}

	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// 得到单元格内容的值
		lastContents += new String(ch, start, length);
	}

}

 

分享到:
评论
1 楼 hqingjin 2012-05-18  
读取excel的程序的入口方法和获取结果的方法是哪一个?方法之间好像关联性不太强啊。。。。。

相关推荐

    使用Poi读取大数据量excel的方法

    在Java开发中,Apache POI库是一个非常实用的工具,用于读取...总之,Apache POI结合SAX API为在Android上处理大数据量Excel文件提供了有效方案,通过合理配置和优化,可以显著降低内存消耗,提高应用的稳定性和效率。

    java poi 导入大数据量Excel数据 防止内存溢出处理.zip

    Java中的Apache POI库是用于读取和...通过以上策略,可以有效地处理Java POI在导入大数据量Excel时的内存溢出问题,同时提高程序的运行效率。在实践中,应根据具体场景选择合适的优化方法,确保程序的稳定性和性能。

    Java解析大数据量Excel,可解析1048576行excel

    在处理大数据量的Excel文件时,Java是一种常用的语言,因为它提供了强大的库,如Apache POI,使得解析大型Excel文件成为可能。Apache POI是Java的一个开源项目,专门用于读写Microsoft Office格式的文件,包括Excel...

    java poi 读取百万数据OOM优化

    EasyExcel是阿里巴巴开源的一个轻量级Java库,专门针对大数据量的Excel读写进行了优化。EasyExcel通过事件驱动的模型,只在内存中保留当前处理的行数据,极大地降低了内存消耗。从描述来看,EasyExcel的读取速度比...

    Java通过POI读取Excel遍历数据,批量生成word文档

    本教程将重点讲解如何使用Apache POI库来读取Excel数据,并基于这些数据批量生成Word文档。Apache POI是一个开源项目,它允许Java开发者处理Microsoft Office格式的文件,如Excel(.xlsx或.xls)和Word(.docx)。 ...

    java读取excel之xlsl超大文件

    然而,当处理的Excel文件特别是XLSL格式的文件数据量巨大时,传统的API,如Apache POI或者JExcelAPI,可能会遇到性能问题,因为它们会一次性加载整个工作簿到内存中,可能导致内存溢出。为了解决这个问题,我们需要...

    读取大数据量的excel文件

    本案例采用的poi读取大数据的excel文件 usermodel模式对excel操作前需要将文件全部转入内存,对较大文件来说内存开销很大。但是其使用简单。 eventusermodel模式采用事件模型,对文件边读取边处理,内存消耗较低,...

    poi大量数据读取gc内存溢出解决方案

    poi读取大量数据会造成gc内存溢出的报错,由于垃圾回收机制无法将大量的对象及时的回收,而这些对象又会保存在内存中,会导致内存不够用的情况,这时候我们就需要使用新的方法,读取为cvs即可.此解决方案可支持千万数据的...

    POI百万级大数据量EXCEL导出 - 请叫我猿叔叔的博客 - CSDN博客.htm

    POI百万级大数据量EXCEL导出 - 请叫我猿叔叔的博客 - CSDN博客.htm

    java使用 poi 读取excel

    Java 使用 Apache POI 读取 Excel 是一个常见的任务,在处理数据导入、导出或数据分析时非常有用。Apache POI 是一个流行的开源库,它允许 Java 开发者创建、修改和显示 Microsoft Office 格式的文件,其中包括 ...

    java读取excel文件POI+jxl

    在Java中,读取和操作Excel文件是常见的需求,这通常涉及到使用库,如Apache POI和JXL。这两个库都允许开发者在Java中方便地读取、写入和修改Excel文件。 Apache POI是一个强大的库,专门用于处理Microsoft Office...

    使用Poi读取大数据量excel的方法-Java代码类资源

    本资源“使用Poi读取大数据量excel的方法”提供了处理大量数据时使用POI进行有效读取的示例代码。以下是关于如何使用POI高效地处理大数据量Excel文件的一些关键知识点: 1. **POI组件**: - HSSF:处理Excel 97-...

    Java poi基于事件驱动读取excel 2007海量数据 处理空单元格

    该压缩包里面有两个文件,TestExcel.java主要是原始的处理方法,操作简单,适合小数据量的读取。 ExampleEventUserModelUtil.java是处理大数据量的。users40.xlsx是测试文件,里面有40万条数据。 jar包都在jar文件夹...

    使用POI导出大数据量到EXCEL

    通过以上步骤,我们可以在Java中使用Apache POI实现大数据量的Excel导出。实际开发中,可能还需要考虑如数据分页、数据过滤、多线程处理等高级功能,以进一步提高性能和用户体验。记得在使用完毕后释放资源,如关闭...

    完美解决java读取excel内存溢出问题.rar

    总结来说,解决Java读取Excel内存溢出问题,关键在于合理利用资源、优化代码逻辑以及选择适合的API,如Apache POI的SXSSF。通过这些方法,我们可以在不显著增加系统资源负担的情况下,高效地处理大Excel文件。

    Java实现Excel读写的poi 5.2.1版本jar

    在这个5.2.1版本中,POI提供了对Excel电子表格的强大支持,包括读取数据、修改内容、创建新工作簿以及处理复杂的公式和样式。 `poi-ooxml-lite-5.2.1.jar`:这个轻量级的JAR文件包含了处理OOXML(Office Open XML)...

    ExcelUtil借助反射和POI对Excel读取,省略了以往读取Excel的繁琐步骤

    这样,对于不同结构的Excel文件,只需要改变输入的Bean类,就能轻松读取数据。 兼容03/07版Excel的功能意味着ExcelUtil支持两种主要的Excel文件格式:.xls(97-2003版本)和.xlsx(2007及以上版本)。这得益于...

    java读取数据量大的excel文件(2003及2007)

    综上所述,Java读取大型Excel文件涉及的关键点在于选择合适的API,采用分块读取、迭代器、错误处理、性能优化和可能的数据库集成。理解并应用这些技术将帮助你在处理大数据量的Excel文件时更加得心应手。

    java中使用poi导出Excel大批量数据到客户端

    在java web系统应用中我们经常会用到大批量数据的导出,动辄就上几十万几百万的数据让我们的程序感觉...java中使用poi导出Excel大批量数据到客户端 存在两个导出方法:存在一个分批量导出ZIP文件,一个导出exel文件

Global site tag (gtag.js) - Google Analytics