在Java中,如何从后到前迭代文本文件中的行

时间:2010-04-03 15:58:01

标签: java file fileinputstream

基本上我需要一个文本文件,例如:

  

佛瑞德
  伯尼
  亨利

并能够按照

的顺序从文件中读取它们
  

亨利
  伯尼
  佛瑞德

我正在读取的实际文件大于30MB,读取整个文件,将其拆分为数组,反转数组然后从那里开始,这将是一个不完美的解决方案。这需要太长时间。我的具体目标是找到字符串的第一个匹配项(在本例中为“InitGame”),然后返回该行开头的位置。

之前我在python中做过类似的事情。我的方法是寻找文件的末尾 - 1024,然后读取行直到我结束,然后从我之前的起点寻找另一个1024,并且通过使用tell(),当我到达之前的时候我会停止初始点。所以我会从文件末尾向后读取这些块,直到找到我要查找的文本。

到目前为止,我已经厌倦了用Java做这件事。如果您住在巴尔的摩附近,可能会得到一些新鲜出炉的饼干。

谢谢!

更多信息:

我需要向后搜索,因为我正在阅读的文件是我托管服务器的游戏的日志文件(它是城市恐怖的错误服务器。检查出来)。日志文件记录游戏中发生的每个事件,然后我的程序将解析每个事件,处理它然后对其进行操作(例如,它跟踪人们的爆头并且还将自动踢出正在进行d-bag的人)。我需要搜索最新的InitGame条目,以便我可以实例化所有玩家对象并处理自该游戏开始以来需要注意的任何其他内容。文件中有数百个InitGame事件,但我想要最后一个。如果有更好的方法,不需要向后搜索,请告诉我。

由于

4 个答案:

答案 0 :(得分:1)

你可以使用RandomAccessFile重复你的Python解决方案,也可以是LineNumberReader(或者只是Reader)的自定义子类。

答案 1 :(得分:0)

Linux有一些很棒的文本解析工具,可能比尝试用Java做得更好。

答案 2 :(得分:0)

在向后搜索时,会想到两个答案。第一种是向前搜索,并在到达文件末尾时保留最后找到的InitGame文本(并在读取文件时每当另一个InitGame出现时覆盖它)。

第二个解决方案是找出文件大小(使用f.length()),将其划分为大块,重叠超过InitGame片段的最大大小(以避免由于分割两个块的问题而产生的问题)在有趣的部分),并从最后一个开始阅读并向文件开始前进(使用Reader的skip()函数跳转到您想要的阅读位置:不需要实际的文件分割)。如果您确定没有有趣的多字节字符,则RandomAccessFile可能很有用。

当然,最有效的解决方案是在输出时读取日志文件输出,并保留对最后找到的InitGame的引用。这样,您将永远不必重新读取相同的数据两次。您甚至可以进行设置,以便您的Java程序每隔几秒唤醒一次,查看文件,并读入新添加的行。

答案 3 :(得分:0)

所以,当我解释我正在做什么时,我需要更详细的TIL。基本上我正在编写一个管理我运行的游戏服务器的程序。为了使程序与游戏同步,它需要找到最新的InitGame行,然后从那里读取,以便它可以记录从该轮开始所需的所有这些命中,杀死,连接和断开连接。由于日志文件可能非常庞大(我最后一次忘记清理它的文本超过500MB),而不是从前面搜索,我想从后面搜索。在Java中,没有内置的方法来做到这一点。在搜索了大量的互联网之后,我发现了这个:http://mattfleming.com/node/11。从那里我拿出BackwardsFileInputStream类并使用它。然后在我的应用程序中,我反转了字符。下次我应该能够构建自己的方法,现在我已经看到它是如何完成的并且有更好的理解。

因此,一旦程序从最新的InitGame读取了日志文件,它将模仿tail -f并在写入时读取日志文件。