首页 文章

在Apache Poi中调用trackAllColumnsForAutoSIzing有什么内存含义

提问于
浏览
1

使用Apache Poi我已经将我的代码转换为将数据写入从HSSF到SXSSF的Excel电子表格,以便在编写大文件时减少内存占用 . 我遇到的一个问题是根据数据调整列的大小

for (int 0 = 1; i < next.getMapping().size(); i++)
{
     next.getSheet().autoSizeColumn(i);
}

现在失败抱怨我的专栏没有跟踪

我先修改了这个问题

((SXSSFSheet)next.getSheet()).trackAllColumnsForAutoSizing();

这行和我在最后保存之前调用的调整大小代码

workbook.write(fos);
fos.close();
workbook.dispose();

我不清楚的是

  • 这样的内存含义,是否突然必须将所有数据读入内存中,或者只是迭代查找最长的值

  • 我只在最后这样做,所以它实际上是考虑所有数据或只是最后的 n 行,其中 n 是最初构造的SXSSFWorkbook时使用的值

Update 所以我在[https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFSheet.html#trackAllColumnsForAutoSizing()]查看了SXSSFSheet的javadoc,它说

调整列宽以适合内容 . 对于大型工作表,此过程可能相对较慢,因此通常只应在处理结束时每列调用一次 . 您可以指定是否应考虑或忽略合并单元格的内容 . 默认是忽略合并的单元格 . 关于SXSSF实现的特别说明:您必须使用trackColumnForAutoSizing(int)或trackAllColumnsForAutoSizing()在SXSSFSheet中注册要跟踪的列 . 这是必需的,因为计算列宽所需的行可能已经落在随机访问窗口之外并被刷新到磁盘 . 即使所有行都在随机访问窗口中,也需要跟踪列 . POI 3.14 beta 1中的新功能:使用当前行和刷新行中的单元格自动调整列 .

它没有给出关于内存缓慢的任何警告,并且它还说它考虑了所有行但我在3.15并且我认为它不考虑所有行 . 我有一些列,其中数据占用第0行中列 Headers 的空间较小,但创建的电子表格的列宽度小于第一行中 Headers 的宽度 .

当我处理每一行并存储最宽的数据时,我可以很容易地存储数据的宽度 . 但是,虽然我可以使用setColumnWidth(),但如何考虑不同的字体

1 回答

  • 2

    因为Apache POI是开源的,所以你可以read the implementation code and see how it works!

    跟踪列没有太大的内存占用影响,因为主存储每列只有一个对象:

    Map<Integer, ColumnWidthPair> maxColumnWidths = 
                                  new HashMap<Integer, ColumnWidthPair>();
    

    跟踪将会减慢行的添加速度,因为对于跟踪列中的每个单元格,POI必须计算出将单元格刷回磁盘之前的宽度 .

    如果您的文件是可预测的,通常最好打开所有列的跟踪,写出前10行,然后关闭跟踪到文件的末尾 . 这样就可以很好地猜测宽度,而无需计算每个单元格 .

    但是,如果您不知道哪个行将包含每个单元格的最长值,那么'll need to take the slight performance hit and track all columns and all rows throughout the file. It'不会比不执行它更多的工作

相关问题