【问题标题】:Infinite while loop with an iterator, hasNext() and next()带有迭代器的无限 while 循环,hasNext() 和 next()
【发布时间】:2015-06-25 09:03:56
【问题描述】:

我正在开发一个 Java 项目,该项目使用 Apache POI 来操作 .docx 文件。两天前我遇到了一个问题,我无法解决。我真的不知道,我的错误在哪里,以及是什么原因造成的。我唯一知道的是,这个错误在做什么。

两天前,一切正常。我选择了我的 .docx,单击了单选按钮,其中定义了将执行哪些更改,然后单击“提交”按钮开始这项工作。 它的工作原理是这样的:使用 Apache POI 方法从 .docx 中获取所有文本,遍历每个 Run,更改关键字和语法,然后将更新的 Paragraph 及其运行放回文档中。对于第二个单选按钮的更改,该过程重复。最后,带有两个单选按钮更改的文档将在其文件名中使用后缀保存。 如果我现在选择一个特殊的单选按钮,则操作会成功运行整个文档。但是,在操作第二次运行(由第二个单选按钮定义)期间,执行看起来像是在特定点冻结,因为 Eclipse 控制台没有显示任何更改。事实上,如果我终止应用程序并查看生成的文档,我会看到,同一段文本被一遍又一遍地粘贴到文档中。该文件长约 11 页。这种错误的粘贴在几秒钟内将其大小增加了 330 多页。这让我想到,一定有一个无限循环。其他任何事情对我来说都没有多大意义。

奇怪的是,我从未更改过该算法的任何内容(我认为)。我做的最后一件事是将我的 Java 版本更新到 8u45,但是由于我回滚到以前的版本,并且错误仍然存​​在,我看起来不像是更新以某种方式导致了错误。

我希望你们中的某个人能给我一些建议。我不认为,在这里发布我的代码很有用,因为它几乎是其他方法的完整副本,可以正常工作,但无论如何我都会这样做。这种代码的平静是唯一的部分(在选择了有问题的单选按钮之后),我使用了一个 while 循环。所有其他循环都是 for 循环。让我困惑的是:

  • 第一个 radion buttong(有问题的那个)在做什么,以致后续更改的执行以无限循环结束?
  • 如果它是一个无限循环,它是如何写在我的文档中的?如您所见,当我离开 while 循环时,我只将内容写入文档。当我在 Eclipse 中手动终止它时,文档中不应该有任何文本。

    public static void changeSingleMaleToMultiMale(String path, String title, XWPFDocument document) throws Exception
    {
        XWPFDocument oldDoc = document;
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        int length = title.length();
    
        int counter = 0;
    
        while(iterator.hasNext())
        {
            XWPFParagraph paragraph = iterator.next();              
            System.out.println("____ unchanged\n" + paragraph.getText() + "\n____\n\n");
    
            List<XWPFRun> runs = paragraph.getRuns();
    
    
            for(int i = 0; i < runs.size(); i++)
            {
                String text = runs.get(i).toString();
    
    
                if(text.contains(title))
                {
                    runs.get(i).setText(StringFunctions.fromSingleMaleToMultiMale(text, title, length), 0); 
                }   
            }
            System.out.println("____ updated\n" + paragraph.getText() + "\n____\n\n");
            document.setParagraph(paragraph, counter);
            counter++;
        }
    
        try {
    
            FileOutputStream output = new FileOutputStream(path.substring(0, path.length()-5) + "Aktualisiert.docx");
            document.write(output);
            output.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

有没有人经历过类似的事情?对于解决这个问题的每一个小提示,我都会很高兴。

更新:通过选择提到的单选按钮调用的错误代码不会影响由其他单选按钮调用的方法。它看起来像这样。事实上,代码的错误和平将如此巨大的文本写入我的变量,此时我认为,输出流仍在忙于将巨大的文本写入我的文档,而以下方法正在尝试访问该文档。到目前为止,这回答了上面列表中的第一个问题。另一个问题和问题仍然悬而未决。

【问题讨论】:

  • TLDR;调试器说什么?
  • 好主意,给我几分钟检查一下。我还没有使用调试器,因为我有一堆 printlns,它们为我提供了有关代码中每个步骤的准确信息......好吧,从现在开始。
  • 你拥有宇宙的所有时间 :)
  • 同时你可以检查我的更新/编辑,如果你想这样做,不知道这是否能提供更多的洞察力。 :)
  • 所以,我使用调试器检查每一步得到的结果。似乎每一步都一切正常。这意味着我可以检查每个初始运行,检查我的操作结果,以及之间的一些步骤。一切看起来都是正确的。重复的文本在文档开头的某处发送垃圾邮件。调试器此时不会出错,并且会更进一步。这让我想,如果文本传输到输出流或类似的东西不正确。哦,没有异常或错误输出。

标签: java iterator apache-poi infinite-loop next


【解决方案1】:

几天前我找到了解决方案。

即使看起来像这样,也没有无限循环,因为同一段文本在我的文档中被粘贴了数千次。

经过一段绝望的时间,试图找出为什么我的循环无法正常工作,我决定吞下苦果,并尝试逐步找出导致错误的原因。

所以我把大部分代码都放到了cmets中,并把每一段代码都去掉注释,一步一步来。我发现,循环已正确实现,并且错误隐藏在方法中,这有助于替换文档中的一些文本。

我得到了这样的东西:

String checkString = "";

作为我的变量的简单初始值。

在某些特殊情况下,“checkString”会得到一个字符串,在其他一些情况下,它应该保留为空字符串。

错误在于处理第二种情况。我有一个这样定义的 if 子句:

if(baseString.contains(checkString))

你看到这里,如果“checkString”是一个空字符串会发生什么? 是的,当然,无论如何,“baseString”都包含“”。 那个 if 子句每次都是真的。这个 if 子句中的其他行做了一些工作,这导致看起来像是无限粘贴文本。

if(checkString != "" && baseString.contains(checkString))

修复一切。

错误的表现方式让我想到,错误无处不在,但不是在那个方法中。有趣的是,这些简单的错误如何让我如此生气。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    相关资源
    最近更新 更多