Ответ 1
Я также обработал несколько тысяч больших файлов excel, и, на мой взгляд, POI очень быстро. Загрузка файлов excel занимает около 1 минуты в самом Excel. Поэтому я бы подтвердил, что проблема заключается в коде POI
У меня есть электронная таблица, которую я пытаюсь прочитать с помощью POI (у меня есть форматы xls и xlsx), но в этом случае проблема связана с файлом xls. Моя таблица имеет около 10 000 строк и 75 столбцов, а чтение ее может занять несколько минут (хотя Excel открывается через несколько секунд). Я использую чтение на основе событий, а не чтение всего файла в память. Мясо моего кода ниже. Это немного беспорядочно сейчас, но это действительно просто длинный оператор switch, который был в основном скопирован из примеров POI.
Является ли типичным для производительности POI использование модели событий так медленно? Есть ли что-то, что я могу сделать, чтобы ускорить это? Я думаю, что несколько минут будут неприемлемыми для моего приложения.
POIFSFileSystem poifs = new POIFSFileSystem(fis);
InputStream din = poifs.createDocumentInputStream("Workbook");
try
{
HSSFRequest req = new HSSFRequest();
listener = new FormatTrackingHSSFListener(new HSSFListener() {
@Override
public void processRecord(Record rec)
{
thisString = null;
int sid = rec.getSid();
switch (sid)
{
case SSTRecord.sid:
strTable = (SSTRecord) rec;
break;
case LabelSSTRecord.sid:
LabelSSTRecord labelSstRec = (LabelSSTRecord) rec;
thisString = strTable.getString(labelSstRec
.getSSTIndex()).getString();
row = labelSstRec.getRow();
col = labelSstRec.getColumn();
break;
case RKRecord.sid:
RKRecord rrk = (RKRecord) rec;
thisString = "";
row = rrk.getRow();
col = rrk.getColumn();
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord) rec;
thisString = lrec.getValue();
row = lrec.getRow();
col = lrec.getColumn();
break;
case BlankRecord.sid:
BlankRecord blrec = (BlankRecord) rec;
thisString = "";
row = blrec.getRow();
col = blrec.getColumn();
break;
case BoolErrRecord.sid:
BoolErrRecord berec = (BoolErrRecord) rec;
row = berec.getRow();
col = berec.getColumn();
byte errVal = berec.getErrorValue();
thisString = errVal == 0 ? Boolean.toString(berec
.getBooleanValue()) : ErrorConstants
.getText(errVal);
break;
case FormulaRecord.sid:
FormulaRecord frec = (FormulaRecord) rec;
switch (frec.getCachedResultType())
{
case Cell.CELL_TYPE_NUMERIC:
double num = frec.getValue();
if (Double.isNaN(num))
{
// Formula result is a string
// This is stored in the next record
outputNextStringRecord = true;
}
else
{
thisString = formatNumericValue(frec, num);
}
break;
case Cell.CELL_TYPE_BOOLEAN:
thisString = Boolean.toString(frec
.getCachedBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
thisString = HSSFErrorConstants
.getText(frec.getCachedErrorValue());
break;
case Cell.CELL_TYPE_STRING:
outputNextStringRecord = true;
break;
}
row = frec.getRow();
col = frec.getColumn();
break;
case StringRecord.sid:
if (outputNextStringRecord)
{
// String for formula
StringRecord srec = (StringRecord) rec;
thisString = srec.getString();
outputNextStringRecord = false;
}
break;
case NumberRecord.sid:
NumberRecord numRec = (NumberRecord) rec;
row = numRec.getRow();
col = numRec.getColumn();
thisString = formatNumericValue(numRec, numRec
.getValue());
break;
case NoteRecord.sid:
NoteRecord noteRec = (NoteRecord) rec;
row = noteRec.getRow();
col = noteRec.getColumn();
thisString = "";
break;
case EOFRecord.sid:
inSheet = false;
}
if (thisString != null)
{
// do something with the cell value
}
}
});
req.addListenerForAllRecords(listener);
HSSFEventFactory factory = new HSSFEventFactory();
factory.processEvents(req, din);
Я также обработал несколько тысяч больших файлов excel, и, на мой взгляд, POI очень быстро. Загрузка файлов excel занимает около 1 минуты в самом Excel. Поэтому я бы подтвердил, что проблема заключается в коде POI
f вы используете POI Apache для создания большого файла excel, обратите внимание на следующую строку:
sheet.autoSizeColumn((short) p);
Потому что это ухудшит производительность.
Я попытался бы использовать потоковое hssf, также введенное в poi-beta3. Это помогло проблемам с памятью на больших таблицах с 1000 + столбцами.
Я сделал более подробное профилирование, и похоже, что проблема действительно в коде вне POI. Я просто предположил, что это было узким местом, но я считаю, что это неверно.
Если вы используете Apache POI для создания большого файла excel, обратите внимание на sheet.autoSizeColumn((short) p); потому что это повлияет на производительность.
http://stanicblog.blogspot.sg/2013/07/generate-large-excel-report-by-using.html