将大文本文件数据写入excel

时间:2013-05-14 08:36:05

标签: java apache-poi aspose

我正在阅读一些用分隔符分隔的文本文件。

我的文本文件内容示例

Avc def efg jksjd
1 2 3 5
3 4 6 0

逐行并使用具有行号作为整数类型键的散列映射将其保存在内存中 每行文本文件为List对象

考虑一下,我的地图会存储这样的信息

整数列表

1 [Avc def efg jksjd]

我正在使用Apache POI写入excel。 使用Apache POI写入excel时,我遵循这种方法,这是我的代码片段

HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Sample sheet");
Map<Integer, List<Object>> excelDataHolder = new LinkedHashMap<Integer, List<Object>>();
int rownum = 0;
for (Integer key : keyset) {
            Row row = sheet.createRow(rownum++);
            List<Object> objList = excelHolder.get(key);//excelHolder is my map
            int cellnum = 0;
            for (Object obj : objList) {
                Cell cell = row.createCell(cellnum++);
                    cell.setCellValue((Date) obj);
            }
}

如果要写入excel的行/记录数量较少,则此方法非常有效。想象一下,如果记录是十亿个数字,或者如果文本文件中有更多的行假设为10万个。我想,我的方法失败了,因为 createRow和createCell在堆中创建超过10万个对象。 无论java是excel api,我认为写入它(excel)是基于相同的方法,即如上所示的集合迭代。我也用aspose做了一些例子,因此aspose也有同样的问题。

  • createRow和createCell每次调用时都会创建新对象吗?
  • 如果是,有什么替代方案?如何以更好的性能将大数据写入Excel?

4 个答案:

答案 0 :(得分:3)

最新版本的apache-poi有sxssf。来自网站的无耻副本

  

SXSSF(包:org.apache.poi.xssf.streaming)是API兼容的   在非常大的电子表格中使用XSSF的流扩展   必须生产,堆空间有限。 SXSSF实现了低价   通过限制对a内的行的访问来限制内存占用   滑动窗口,而XSSF可以访问文档中的所有行。   不再在窗口中的旧行变得无法访问,如   它们被写入磁盘。

我用它创建了150万行的电子表格。

答案 1 :(得分:2)

我将回答Aspose.Cells for Java,因为你也尝试过。

创建或加载非常大的Excel文件几乎总是需要大容量内存。即使您一次只读取一行或多行,您仍然会将内容写入工作簿的实例,该工作簿将加载到内存中。

解决方案1(不好且非常有限):增加堆大小,如果允许的最大堆大小适用于您的最大文件,请选择它。

解决方案2(与某些手动工作相结合): Excel 2007及更高版本允许每张大约100万行。我建议你创建一个只有一张100万行的工作簿。也就是说,如果文本文件中有1000万行,则创建10个单独的Excel工作簿。

稍后,将它们手动组合到一个Excel工作簿中。在复制具有如此庞大数据的工作表时,Aspose.Cells会给出内存不足的异常。

以下是创建10个单独Excel文件的代码段,每个文件包含100万行。

import com.aspose.cells.*;
import java.util.*;

public class ExcelLargeTextImport
{
    private static String excelFile = Common.dataDir + "largedata.xlsx";

    public static void main(String args[])
    {
        try
        {
            Common.setLicenses();
            importToExcel();
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
        }
    }

    private static void importToExcel() throws Exception
    {
        // Process each workbook in a method
        for (int sheetCounter=0 ; sheetCounter<10 ; sheetCounter++)
        {
            saveWorkbook(sheetCounter);
        }
    }

    private static void saveWorkbook(int sheetCounter) throws Exception
    {
        Workbook workbook = new Workbook();
        // Get the first sheet 
        Worksheet worksheet = workbook.getWorksheets().get(0);
        Cells cells = worksheet.getCells();

        // Initialize array list with 1 million records
        ArrayList<String> lines = new ArrayList<String>();
        int rowCount = 1000000;
        for (int i=0 ; i<rowCount ; i++)
        {
            lines.add(i + ";value1;value2;value3");
        }

        long lineNo = 1;
        for (String line : lines)
        {
            // Split the line by delimeter
            String[] values = line.split(";");

            // First cell
            Cell cell = cells.get("A" + lineNo);
            cell.setValue(values[0]);

            // Second cell
            cell = cells.get("B" + lineNo);
            cell.setValue(values[1]);

            // Third cell
            cell = cells.get("C" + lineNo);
            cell.setValue(values[2]);

            // Fourth cell
            cell = cells.get("D" + lineNo);
            cell.setValue(values[2]);

            lineNo++;
        }
        System.out.print(sheetCounter + " ");

        // Saving the Excel file
        workbook.save(excelFile.replace(".xlsx", sheetCounter + ".xlsx"));

        System.out.println("\nExcel file created");
    }
}

PS。我是Aspose的开发人员传播者。

答案 2 :(得分:1)

为什么不以块的形式进行读写操作。这是我能想到的方法:

  • 读取您的txt文件中的几行,然后将信息放在地图中。假设你读了100行,你的地图中有100个条目。
  • 将这100个条目写入excel文件,第一次创建excel
  • 清空地图或重新初始化。
  • 现在阅读下一行100行文本。据我所知,没有读取前100行就无法直接访问第101行。因此,您可能必须从头开始读取文件,但您可以避免前100行并在地图中创建条目。
  • 现在更新excel文件。我认为您可以使用此链接中提到的POI更新Excel: Edit existing excel files using jxl api / Apache POI

如果你继续迭代这个过程。你肯定会节省你的内存消耗,虽然我没有看到cpu消耗的主要差异。

希望它有所帮助!

答案 3 :(得分:0)

这是你的回答......

试试这个简单的代码&amp;如果您还需要未来,您可以广告...

https://stackoverflow.com/a/16479713/1490962