【问题标题】:Can you jump a scanner to a location in file or scan backwards?您可以将扫描仪跳转到文件中的某个位置或向后扫描吗?
【发布时间】:2011-03-05 02:38:30
【问题描述】:

我有一个非常大的文本文件,我需要从接近末尾的某个地方收集数据。也许 Scanner 不是执行此操作的最佳方法,但是在到达我感兴趣的文件部分之前从顶部开始并抓取 6000 行会非常浪费。有没有办法告诉 Scanner 跳转到说文档向下 7/8 处还是从底部开始逐行向上扫描?

谢谢

【问题讨论】:

  • 6000 行听起来并不多。你试过了吗?这是否经常运行,足以使一切复杂化?
  • 6000 只是我淡化的文本文件。我担心该领域的文件要大得多。我还非常关注程序的响应能力,我不想让系统进行任何不需要的处理。

标签: java java.util.scanner


【解决方案1】:

Scanner 包装了一个InputStream,您可以使用流的skip(long) 方法跳过您不想要的行然后开始扫描。

阅读更多内容InputStreamjavadoc

【讨论】:

  • 显而易见的困难是skip 不会跳过,它会跳过字节,而且无法知道有多少字节在每一行中而不阅读它们。但这是跳过一些数据的好方法。
  • @Mark Peters:很棒的评论 - 我没有考虑到这一点。
  • 这对我来说还是很有用的。感谢您的帮助。
【解决方案2】:

你应该改用RandomAccessFile

【讨论】:

  • RandomAccessFile 如果需要按顺序读取内容,则不好。
【解决方案3】:

java.util.Scanner 的基础输入源是java.lang.Readable。除了Scanner(File) 构造函数之外,Scanner 既不知道也不关心它正在扫描文件的事实。

此外,由于它是基于java.util.regex.* 的正则表达式,因此无法向后扫描。

要完成您想做的事情,最好在输入源级别进行,例如通过使用源的InputStream.skip,然后将其传递给Scanner的构造函数。


开启Scanner.skip

Scanner 本身确实有一个skip,并且像"(?s).{10}" 这样的模式会跳过10 个字符(在(?s) 单行/Pattern.DOTALL 模式下),但这可能是一种相当迂回的做法它。

这是一个使用skip 跳过给定行数的示例。

    String text =
        "Line1 blah blah\n" +
        "Line2 more blah blah\n" +
        "Line3 let's try something new \r\n" +
        "Line4 meh\n" + 
        "Line5 bleh\n" + 
        "Line6 bloop\n";
    Scanner sc = new Scanner(text).skip("(?:.*\\r?\\n|\\r){4}");
    while (sc.hasNextLine()) {
        System.out.println(sc.nextLine());
    }

这会打印 (as seen on ideone.com):

Line5 bleh
Line6 bloop

【讨论】:

  • 感谢您的回答。我想我错过了 Scanner API 列表中的跳过功能。我想我会利用 InputStream.skip。
  • @Mike:是的,Mark Peters 是正确的。如果您知道要跳过多少字节,请在 InputStream 级别跳过。如果你不这样做,例如您想跳过一些行,并且输入足够动态,您无法对其进行预处理以从中创建索引,然后只需Scanner.skip。不用说,这个方法跳过了匹配输入,所以它实际上做了相当多的工作。
  • skip 部分在我尝试在静态方法中放置参数而不是 4 时给了我 java.lang.StackOverflowError
猜你喜欢
  • 2019-10-22
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多