6

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

我的文本文件内容示例

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 的行数/记录数较少,这将非常有效。想象一下,如果记录以十亿为单位,或者如果文本文件有更多行假设为 100 000。我认为,我的方法失败了,因为 createRow 和 createCell 在堆中创建了超过 100 000 个对象。无论 java 到 excel api,我认为写入它(excel)是基于相同的方法,即,如上所示的集合迭代。我也用 aspose 做了一些例子,结果 aspose 我猜也有同样的问题。

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

4 回答 4

3

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

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

我用它来创建包含 150 万行的电子表格。

于 2013-05-14T09:42:07.580 回答
2

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

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

解决方案 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 的开发人员布道师。

于 2013-05-15T07:25:29.650 回答
1

为什么不分块进行读写。这是我可以考虑的方法:

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

如果你不断迭代这个过程。你肯定会节省你的内存消耗,尽管我没有看到 CPU 消耗有很大的不同。

希望能帮助到你!

于 2013-05-14T08:50:15.793 回答
0

这是你的答案...

试试这个简单的代码&如果你需要更多的未来,你可以广告......

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

于 2013-05-14T09:32:50.407 回答