逐行迭代文本文件的内容 - 是否有最佳实践? (与PMD的AssignmentInOperand相比)
我们有一个 Java 应用程序,它有一些能够读取文本文件的模块。他们使用这样的代码非常简单:
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null)
{
... // do stuff to file here
}
我在我的项目上运行了PMD,并在while (...)<中遇到了“AssignmentInOperand”违规。 /代码>行。
除了显而易见的方法之外,是否还有更简单的方法来执行此循环:
String line = br.readLine();
while (line != null)
{
... // do stuff to file here
line = br.readLine();
}
这是否被认为是更好的实践? (尽管我们“复制”了 line = br.readLine()
代码?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我知道这是一篇旧帖子,但我(几乎)有同样的需求,我使用 Apache Commons 中 FileUtils 的 LineIterator 解决了它。
从他们的 javadoc:
检查文档:
http://commons .apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/LineIterator.html
I know is an old post but I just had the same need (almost) and I solve it using a LineIterator from FileUtils in Apache Commons.
From their javadoc:
Check the documentation:
http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/LineIterator.html
对 流 和 java-8 和 Try-With-Resources 允许您以更紧凑的语法实现您想要的效果。
The support for streams and Lambdas in java-8 and Try-With-Resources of java-7 allows you to achive what you want in more compact syntax.
我经常使用
while((line = br.readLine()) != null)
构造...但是,最近我遇到了这个不错的替代方案:这仍然是重复
readLine()
调用代码,但逻辑很清晰,等等。另一次我使用
while(( ... ) ...)
构造是从流读取到byte[]
数组时...这也可以转换为 for 循环with:
我不确定我是否真的更喜欢 for 循环替代方案......但是,它会满足任何 PMD 工具,并且逻辑仍然清晰,等等。
I routinely use the
while((line = br.readLine()) != null)
construct... but, recently I came accross this nice alternative:This is still duplicating the
readLine()
call code, but the logic is clear, etc.The other time I use the
while(( ... ) ...)
construct is when reading from a stream in to abyte[]
array...This can also be transformed in to a for loop with:
I am not sure I really prefer the for-loop alternatives.... but, it will satisfy any PMD tool, and the logic is still clear, etc.
我一般更喜欢前者。我一般不喜欢比较中的副作用,但这个特定的例子是一个惯用语,它是如此常见和方便,以至于我不反对它。
(在 C# 中,有一个更好的选择:返回一个
IEnumerable
的方法,您可以使用 foreach 对其进行迭代;这在 Java 中没有那么好,因为在末尾没有自动处置增强的 for 循环...而且还因为您不能从迭代器中抛出 IOException,这意味着您不能只是将其中一个替换为另一个。)方式:重复行问题比操作数内赋值问题更困扰我。我习惯于一目了然地接受这种模式 - 对于重复的行版本,我需要停下来检查一切是否都在正确的位置。这可能是一种习惯,但我不认为这是一个问题。
I generally prefer the former. I don't generally like side-effects within a comparison, but this particular example is an idiom which is so common and so handy that I don't object to it.
(In C# there's a nicer option: a method to return an
IEnumerable<string>
which you can iterate over with foreach; that isn't as nice in Java because there's no auto-dispose at the end of an enhanced for loop... and also because you can't throwIOException
from the iterator, which means you can't just make one a drop-in replacement for the other.)To put it another way: the duplicate line issue bothers me more than the assignment-within-operand issue. I'm used to taking in this pattern at a glance - with the duplicate line version I need to stop and check that everything's in the right place. That's probably habit as much as anything else, but I don't think it's a problem.
根据 Jon 的回答,我认为创建一个装饰器来充当文件迭代器应该很容易,这样您就可以使用 foreach 循环:
公平警告:这会抑制读取期间可能发生的 IOExceptions,并简单地停止读取过程。目前还不清楚 Java 中是否有一种方法可以解决这个问题,而不会引发运行时异常,因为迭代器方法的语义已明确定义,并且必须遵守才能使用 for-each 语法。另外,在这里运行多个迭代器会产生一些奇怪的行为;所以我不确定这是否值得推荐。
不过,我确实对此进行了测试,并且确实有效。
无论如何,您可以使用 for-each 语法作为一种装饰器来受益:
Based on Jon's answer I got to thinking it should be easy enough to create a decorator to act as a file iterator so you can use a foreach loop:
Fair warning: this suppresses IOExceptions that might occur during reads and simply stops the reading process. It's unclear that there's a way around this in Java without throwing runtime exceptions as the semantics of the iterator methods are well defined and must be conformed to in order to use the for-each syntax. Also, running multiple iterators here would have some strange behavior; so I'm not sure this is recommended.
I did test this, though, and it does work.
Anyway, you get the benefit of for-each syntax using this as a kind of decorator:
我有点惊讶没有提到以下替代方案:
在 Java 8 之前,它是我最喜欢的,因为它清晰且不需要重复。 IMO,
break
是具有副作用的表达式的更好选择。不过,这仍然是一个习语问题。I'm a bit surprised the following alternative was not mentioned:
Before Java 8 it was my favorite because of its clarity and not requiring repetition. IMO,
break
is a better option to expressions with side-effects. It's still a matter of idioms, though.Google 的 Guava Libraries 提供了使用静态方法的替代解决方案CharStreams.readLines(Readable, LineProcessor) 以及用于处理每一行的
LineProcessor
实现。while
循环的主体现在放置在LineProcessor
实现中。Google's Guava Libraries provide an alternative solution using the static method CharStreams.readLines(Readable, LineProcessor<T>) with an implementation of
LineProcessor<T>
for processing each line.The body of the
while
loop is now placed in theLineProcessor<T>
implementation.在 PMD 中,AssignmentInOperand 是一个有争议的规则,该规则的原因是:“这会使代码更加复杂且难以阅读”(请参考 http://pmd.sourceforge.net/rules/controversial.html)
如果您确实想这样做,您可以禁用该规则。就我而言,我更喜欢前者。
AssignmentInOperand is a controversial rule in PMD, the reason of this rule is: "this can make code more complicated and harder to read" (please refer http://pmd.sourceforge.net/rules/controversial.html)
You could disable that rule if you really want to do it that way. In my side I prefer the former.