希望能更清楚地了解 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}" 不只匹配我想要的单个字符...不知道为什么会这样?
- Scanner 通过不断读取尽可能多的数据并抢先将数据解析为令牌来更改 InputStream。我倾向于相信这是真的,因为当我在 InputStream 上打印 available() 调用的结果时,在我第一次调用 next() 并将分隔符设置为 "\n 后,可用字节数变为零”。这意味着更改定界符中间处理对于 Scanner 来说非常令人困惑,并且看起来它的行为错误?
任何正则表达式/扫描仪专业知识将不胜感激,谢谢!
PS 我刚刚自己从 InputStream 中读取了单个字节,并在行模式下手动查找“\n”……不漂亮,但按我想要的方式工作。