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

时间:2017-03-15 12:22:07

标签: java apache-poi

使用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();

我不清楚的是

  1. 这样的记忆含义,是否突然必须将所有数据读入内存,或者只是迭代寻找最长的值
  2. 我最后才这样做,所以它实际上是考虑所有数据还是最后的 n 行,其中 n 是最初构建的SXSSFWorkbook时使用的值
  3. 更新 所以我在[https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFSheet.html#trackAllColumnsForAutoSizing()]查看了SXSSFSheet的javadoc 它说

      

    调整列宽以适合内容。

         

    这个过程在大型纸张上可能相对较慢,因此应该这样做   通常每列只调用一次,在你的结尾   处理。您可以指定合并单元格的内容是否应该   被考虑或忽略。默认是忽略合并的单元格。

         

    关于SXSSF实现的特别说明:您必须注册列   您希望使用SXSSFSheet进行跟踪   trackColumnForAutoSizing(int)或trackAllColumnsForAutoSizing()。这个   是必需的,因为计算列宽所需的行可能有   落在随机访问窗口之外并被刷新到磁盘。   即使所有行都在随机访问中,也需要跟踪列   窗口。

         

    POI 3.14 beta 1中的新功能:使用当前单元格自动调整列数   和冲洗的行。

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

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

1 个答案:

答案 0 :(得分:2)

由于Apache POI是开源的,因此您可以read the implementation code and see how it works!

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

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

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

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

但是,如果您不知道哪个行将包含每个单元格的最长值,则您需要获得轻微的性能命中并跟踪整个文件中的所有列和所有行。虽然

,但不是做得多