XSSFSheet 的 removeRow(row) 方法会抛出 ConcurrentModificationException 异常。

3

我正在尝试读取xlsx文件。我正在使用poi 3.10-FINAL。

我的代码是:

FileInputStream fs = new FileInputStream("abc.xlsx");
XSSFWorkbook wb = new XSSFWorkbook(fs);
row_count = 0;

for (int k = 0; k < wb.getNumberOfSheets(); k++) {
    XSSFSheet sheet = wb.getSheetAt(k);
    if (sheet.getLastRowNum() > 0) {
        Iterator<Row> rowIterator = sheet.iterator();

        while (rowIterator.hasNext()) {
            Row row = rowIterator.next(); // throws ConcurrentModificationException
            if (row_count == 0) {
                col_count = row.getLastCellNum();
                //Do something
            } else {
                if (row.getCell(1).equals("XYZ")) {
                    sheet.removeRow(row);  //throws XmlValueDisconnectedException
                }
            }
            row_count++;
        }
    }
}

当我不使用sheet.removeRow(row)执行代码时,它可以正常工作。但是当我添加removeRow调用时,它会抛出XmlValueDisconnectedException异常。
请问有谁能帮我解决这个问题呢?
更新:
令人惊讶的是,我现在得到了ConcurrentModificationException异常。它在执行removeRow()后返回rowIterator.next()时抛出异常。我已经在代码中指明了异常的位置。
堆栈跟踪如下:
java.util.ConcurrentModificationException
    at java.util.TreeMap$PrivateEntryIterator.nextEntry(Unknown Source)
    at java.util.TreeMap$ValueIterator.next(Unknown Source)
    at com.test.app.services.ExecuteImport.uploadFile(ExecuteImport.java:144)
    at com.test.app.controller.MyController.upload(MyController.java:271)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

谢谢。

请添加堆栈跟踪信息。 - Mirco
请查看我的更新问题。 - Naman Gala
那么你已经得到了答案,你正在遍历集合时尝试删除元素。这是不允许的。 - Iootu
那我该如何删除它? - Naman Gala
1个回答

8
如果你在迭代时使用迭代器来删除行,会“困惑”迭代器。请按照以下方式操作:
List<Row> toRemove = new ArrayList<Row>()
  while (rowIterator.hasNext()) {
            Row row = rowIterator.next(); // throws ConcurrentModificationException
            if (row_count == 0) {
                col_count = row.getLastCellNum();
                //Do something
            } else {
                if (row.getCell(1).equals("XYZ")) {
                  toRemove.add(row);
                }
            }
            row_count++;
        }
// loop the list and call sheet.removeRow() on every entry
    ...

同样参见http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html


谢谢,使用你的代码后没有抛出任何异常。但是我有一个问题,在迭代toRemove列表并调用removeRow方法之后,我的Excel表格没有更新。我需要将其写回到同一位置吗? - Naman Gala
是的,但请确保它没有被其他程序打开和使用。 - Mirco
感谢您的帮助。我接受了您的答案。我只有一个问题,removeRow方法是删除行的内容,但它并没有删除该行。因此,在Excel中,我得到了空白行。 - Naman Gala
1
你需要移动剩余的行。请参考https://dev59.com/9YHba4cB1Zd3GeqPWdJB#24927546。但在你的情况下,你需要将它们向上移动。 - Mirco
我有同样的问题,我尝试在循环内使用iterator.remove方法,以便不抛出concurrentmodification异常。但是删除当前行的功能没有起作用。 - Akhil S Kamath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接