【问题标题】:ConcurrentModificationException when trying to replace XWPFHyperlink for XWPFRun尝试为 XWPFRun 替换 XWPFHyperlink 时出现 ConcurrentModificationException
【发布时间】:2018-11-09 16:37:59
【问题描述】:

我正在尝试用超链接替换另一个字符串模式,但我得到了 java.util.ConcurrentModificationException。错误指向的代码行没有意义,所以我无法找出发生了什么。

    // Replace occurrences in all paragraphs
    for (XWPFParagraph p : doc_buffer.getParagraphs()) {
        List<XWPFRun> p_runs = p.getRuns();
        if (p_runs != null) {
            for (XWPFRun r : p_runs) {
                String text = r.getText(0);
                if ((text != null) && (text.contains(pattern))) {
                    if (pattern.equals("LINK_TO_DOCS")) {
                        //TODO
                        String h_url = "http://example.com/linktodocs/";
                        String h_text = replacement;

                        // Creates the link as an external relationship
                        XWPFParagraph temp_p = doc_buffer.createParagraph();
                        String id = temp_p.getDocument().getPackagePart().addExternalRelationship(h_url, XWPFRelation.HYPERLINK.getRelation()).getId();

                        // Binds the link to the relationship
                        CTHyperlink link = temp_p.getCTP().addNewHyperlink();
                        link.setId(id);

                        // Creates the linked text
                        CTText linked_text = CTText.Factory.newInstance();
                        linked_text.setStringValue(h_text);

                        // Creates a wordprocessing Run wrapper
                        CTR ctr = CTR.Factory.newInstance();
                        ctr.setTArray(new CTText[] {linked_text});
                        link.setRArray(new CTR[] {ctr});

                        r = new XWPFHyperlinkRun(link, r.getCTR(), r.getParent());
                    }
                    else {
                        text = text.replaceAll(pattern, replacement);
                        r.setText(text, 0);
                    }

                }
            }
        }
    }

控制台错误:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at releasenotes.ReleaseNotesUpdater.replaceAllOccurrences(ReleaseNotesUpdater.java:263)
at releasenotes.ReleaseNotesUpdater.main(ReleaseNotesUpdater.java:85)

此外,除了这个错误之外,我还想要一些关于如何用超链接替换另一个字符串模式的建议。我已经搜索过,但我对它的工作原理有点困惑。


编辑: 在 java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)

        public Iterator<E> iterator() {
        return new Iterator<E>() {
            private final Iterator<? extends E> i = c.iterator();

            public boolean hasNext() {return i.hasNext();}
            public E next()          {return i.next();}
            public void remove() {
                throw new UnsupportedOperationException();
            }
            @Override
            public void forEachRemaining(Consumer<? super E> action) {
                // Use backing collection version
                i.forEachRemaining(action);
            }
        };
    }

在 java.util.ArrayList$Itr.next(ArrayList.java:859)

        @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

在 java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)

        final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

【问题讨论】:

  • 发布更多堆栈跟踪并指出导致错误的代码行
  • 你在任何地方用过Arrays.asList(...)吗?
  • 项目大小与创建MCVE无关。我有很多大型项目可以从中创建 MCVE。
  • 然后,我将等待其他人对我正在做的事情的方式提出意见,同时我还得进行更多研究。感谢您的宝贵时间。

标签: java apache-poi xwpf


【解决方案1】:

我找到了解决方案,所以如果有人遇到同样的问题,我会分享。

要用超链接运行替换普通运行,只需执行以下操作:

                        String h_url = "http://example.com/index.html";
                        String h_text = replacement;

                        // Creates the link as an external relationship
                        String id = r.getDocument().getPackagePart()
                                .addExternalRelationship(h_url, XWPFRelation.HYPERLINK.getRelation()).getId();

                        // Binds the link to the relationship
                        CTHyperlink link = r.getParagraph().getCTP().addNewHyperlink();
                        link.setId(id);

                        // Creates the linked text
                        CTText linked_text = CTText.Factory.newInstance();
                        linked_text.setStringValue(h_text);

                        // Creates a XML wordprocessing wrapper for Run
                        // The magic is here
                        CTR ctr = r.getCTR();
                        ctr.setTArray(new CTText[] { linked_text });

                        // Stylizing
                        CTRPr rpr_c = ctr.addNewRPr();
                        CTColor color = CTColor.Factory.newInstance();
                        color.setVal("0000FF");
                        rpr_c.setColor(color);

                        CTRPr rpr_u = ctr.addNewRPr();
                        rpr_u.addNewU().setVal(STUnderline.SINGLE);

上面的代码在一个循环中,循环遍历段落中的所有运行(r 是当前运行)。因此,您只需调用 r.getCTR() 即可编辑运行。

异常发生的原因,是因为我试图在这一行中修改文档结构:

 XWPFParagraph temp_p = doc_buffer.createParagraph();

如果有人有任何问题,请随时在 cmets 中提问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2019-05-12
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多