【问题标题】:Understanding java.util.Scanner's effect on InputStream了解 java.util.Scanner 对 InputStream 的影响
【发布时间】:2012-07-06 18:38:14
【问题描述】:

希望能更清楚地了解 Scanner 的内部工作原理...我已经实现了没有 Scanner 所需的功能,但我只是想了解为什么它没有像我想象的那样工作。

上下文:我正在编写一个文本解析器,它需要定期从读取文本行(行模式)切换到从同一输入流中读取设定数量的字节(字节模式)。如果在输入流中看到 BYTE\n,则进入字节模式;后面应该有一个整数,指定要读取的字节数。在有效整数/字节序列后看到 ENDBYTE\n 时退出字节模式。

我尝试使用 Scanner 来实现此解析器,并使用“\n”分隔符以“行模式”读取。我认为如果我将分隔符切换到“。{1}”中流的正则表达式模式,它会开始一次给我一个字节,以便我可以在“原始模式”下处理数据(这是在在我意识到该方法实际上并不仅仅为您提供 InputStream 中的下一个字节之前,浪费了大量时间修补 Scanner.nextByte()。

我尝试将这个序列放入 Scanner 的 InputStream:

BYTE\n32\nNegative, I am a meat popsicle.\nENDBYTE\n

一解析“32\n”,我就尝试将分隔符更改为“.{1}”。如果我随后请求 next(),我得到“\n”,然后 Scanner 奇怪地报告它有更多令牌,但结果却是空的。如果我将分隔符保留为“\n”,我会正确地得到“否定,我是肉冰棒”。作为下一个令牌。

所以我假设:

  1. ".{1}" 不只匹配我想要的单个字符...不知道为什么会这样?
  2. Scanner 通过不断读取尽可能多的数据并抢先将数据解析为令牌来更改 InputStream。我倾向于相信这是真的,因为当我在 InputStream 上打印 available() 调用的结果时,在我第一次调用 next() 并将分隔符设置为 "\n 后,可用字节数变为零”。这意味着在处理过程中更改分隔符对于 Scanner 来说非常令人困惑,并且它看起来会因此而出现错误的行为?

任何正则表达式/扫描仪专业知识将不胜感激,谢谢!

附:我最终自己从 InputStream 中读取了单个字节,并在行模式下手动查找“\n”...不是很漂亮,但可以按我想要的方式工作。

【问题讨论】:

  • 贴出代码相关片段

标签: java regex java.util.scanner


【解决方案1】:

正则表达式 ".{1}"(顺便说一下,与 "." 相同)匹配换行符。

要匹配任何字符包括换行符,请打开正则表达式中的“点匹配换行符”开关:

(?s).


已编辑

我建议不要使用分隔符。只需像这样使用输入:

while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    // do something with line
}

【讨论】:

  • 嗯,基于此,扫描仪似乎是一种非常糟糕的扫描任意字节值的方法?再加上 Scanner 似乎清除了它的 InputStream (这阻止了我告诉 Scanner 等待并让我在将其返回给它之前取出几个字节)这一事实,使得这对于 Scanner 来说似乎是一个糟糕的用例。如果您不同意,请告诉我,谢谢!
  • 不要使用分隔符:只需使用其 API 使用输入。查看编辑后的答案
  • 据我了解,njhwang 想要读取特殊行之间的字节。但是不能保证 Scanner 在从流中读取时不会缓冲任何内容。因此,在“BYTE”行和带有长度参数的行之后从包装的 InputStream 中读取可能会从 Scanner 中的缓冲引起的某个偏移量开始。
  • 是的,@Ame 拥有它的权利。似乎我们同意我不能依赖 Scanner 来保持包装的 InputStream 完整,以便在任意时间在字节级别进行处理。
猜你喜欢
  • 2019-05-03
  • 1970-01-01
  • 2014-02-12
  • 2013-11-21
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 2019-07-12
相关资源
最近更新 更多