我的Excel文件大概有3000行,1000列。
我希望在这个海量数据中进行搜索,我尝试了使用POI,也尝试了比如先取出部分行数,如60行,并且在60行内进行搜索。但不论怎么样,我总是会遇到out of memroy的问题。
这个问题主要是因为POI的内存管理不太好,POI官方提供了SAX事件驱动模式,可以读取大文件。
EasyExcel也可以解决内存溢出的问题:
// 导入依赖包import com.alibaba.excel.EasyExcel;import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import com.alibaba.excel.metadata.Sheet;import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;import java.util.List;@Slf4jpublic class ReadExcelDemo { // 定义要读取的前N行数据的数量 private static final int ROW_COUNT = 1000; public static void main(String[] args) { // 定义要读取的Excel文件路径 String fileName = "path/to/excel/file.xlsx"; // 定义存储读取结果的列表 List<Object> dataList = new ArrayList<>(); // 使用EasyExcel读取Excel文件 EasyExcel.read(fileName, new AnalysisEventListener<Object>() { @Override public void invoke(Object data, AnalysisContext context) { // 判断读取的行数是否超过了设定值 if (context.readRowHolder().getRowIndex() <= ROW_COUNT) { // 将读取的数据存储到列表中 dataList.add(data); } else { // 超过设定值后停止读取 context.interrupt(); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { log.info("Read {} rows of data from Excel file", context.readRowHolder().getRowIndex()); } }).sheet().doRead(); // 处理读取结果 // ... }}
如果可以接受商业软件,可以考虑使用GcExcel。GcExcel 做了相关的处理,优化了内存的使用,不会出问题。同时它的API,使用起来比较简单,API是基于Range(区域),和Excel的概念相似,也有专门的API可以查找或者替换内容。
下面是个示例代码,我们从如下图的Excel文件中进行搜索:
代码:
public void FindText() { // 构建 workbook Workbook wb = new Workbook(); // 打开需要搜索的文件 wb.open("resources/ReplaceExample.xlsx"); // 打开对应的sheet IWorksheet sheet = wb.getWorksheets().get(0); FindOptions findOption = new FindOptions(); findOption.setMatchCase(true); // 获取页面中包含内容的区域 IRange searchRange = sheet.getUsedRange(); // 存储查找到的区域 IRange range = null; // 循环查找 do { // 搜索包含++的格子,本例中会搜索出C++的格子区域 range = searchRange.find("++", findOption); if (range != null) { // 从查找到的区域中取出格子的值 String findVal = range.getValue().toString(); // 获取到值后,进行相关操作 } } while (range != null);}
试试看用hutool的ExcelUtil.readBySax
添加一下maven:
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi --><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.4</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.4</version></dependency>
覆盖实现一下里面的方法:
private RowHandler createRowHandler() { return new RowHandler() { @Override public void handle(int sheetIndex, long rowIndex, List<Object> rowlist) { //遍历excel的每一行你想做什么,sheetIndex是指定sheet,rowIndex是当前行(从0开始),rowList是行数据 //可以用通过rowIndex来限制你要读取的行范围 } };}
ExcelUtil.readBySax(file, 0, createRowHandler());
首先,处理超大的Excel文件时,遇到内存溢出(out of memory)问题是比较常见的。这是因为POI等库会将整个Excel文件加载到内存中,如果文件过大,就会占用大量内存。
如果你只需要读取前N行数据,可以考虑使用Apache的POI-OOXML
库,它支持按行读取Excel文件。这样,你只需要将数据一行行地读出,而不需要将整个文件加载到内存中。
下面是一个基本的代码示例:
import org.apache.poi.ss.usermodel.*;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.Iterator;public class ReadExcel { public static void main(String[] args) throws IOException { // 文件路径 String filePath = "your_excel_file.xlsx"; FileInputStream fis = new FileInputStream(new File(filePath)); // 用WorkbookFactory创建Workbook对象 Workbook workbook = WorkbookFactory.create(fis); // 得到第一页(sheet) Sheet sheet = workbook.getSheetAt(0); // 得到行迭代器 Iterator<Row> rowIterator = sheet.iterator(); int rowCount = 0; while (rowIterator.hasNext() && rowCount < N) { // N为你想读取的行数 Row row = rowIterator.next(); // 这里你可以获取行中的列数据 // ... rowCount++; } }}
在这个代码中,我们首先打开了一个指向你的Excel文件的FileInputStream
。然后我们用WorkbookFactory
创建了一个Workbook
对象,得到了第一个sheet,然后通过迭代器一行行地读取数据。当达到你设定的行数N时,停止读取。注意,你需要替换你的Excel文件路径以及你想读取的行数N。
该编码能够读取excel文件中的小数据...但不读取excel文件中的大数据文件....如何进一步修改代码?
问题内容: 我有一个非常大的数据集,我无法读取其中的整个数据集。因此,我正在考虑只读取其中的一个数据块进行训练,但是我不知道该怎么做。任何想法将不胜感激。 问题答案: 如果您只想读取前999,999行(非标题): 如果您只想读取1,000,000 … 1,999,999行 nrows :int,默认值无要读取的文件行数。对读取大文件有用* skiprows :类似于列表或整数的行号,在文件开始处要
问题内容: 我需要一次最多读取N行来读取一个大文件,直到EOF。在Python中最有效的方法是什么?就像是: 问题答案: 一种解决方案是列表理解和分片运算符: 在这之后是行的元组。但是,这会将整个文件加载到内存中。如果您不希望这样做(即文件可能真的很大),则可以使用生成器表达式和itertools包中的另一种解决方案: 是一个生成器对象,它为您提供文件的每一行,并且可以在这样的循环中使用: 两种解
我遵循这个http://blog.kondratev.pro/2015/08/reading-xlsx-on-android-4-and-hopefully.html对其进行了编码。 尝试逐行读取: 但结果却是:
问题内容: 鉴于我知道路径名和行号,因此我尝试提取文件的单行,理想情况下,我希望这样做是在 不读取任何多余文件的情况下进行的 。 出于我在这里使用的目的,这是异步还是同步都没有关系。 我当前的(不良)实现如下所示: 我尝试使用createReadStream进行操作,但是数据事件似乎从未触发。谁能提供直接解决此问题的方法,或者向我指出一些NodeJS文件系统交互文档,该文档比标准库API文档驱动的
问题内容: 我想读取一个非常大的文件的最后n行,而不使用Java将整个文件读入任何缓冲区/内存区域。 我环顾了JDK API和Apache Commons I / O,但无法找到适合此目的的一个。 我在想UNIX中使用tail或更少的方式。我认为他们不会加载整个文件,然后显示文件的最后几行。在Java中也应该有类似的方法。 问题答案: 如果使用,则可以使用和到达文件末尾附近的特定点,然后从那里开始