为什么Scanner类没有nextChar方法?

33

这只是一种好奇而不是问题...

为什么Scanner类没有nextChar()方法?考虑到它有nextnextIntnextLine等方法,它似乎应该有这个方法。

我知道你可以简单地执行以下操作:

userChar = in.next().charAt(0);
System.out.println( userChar  );

但是为什么不添加一个nextChar()方法呢?


3
作为一种解决方法,您可以尝试使用 next(".") - Joachim Sauer
从源代码来看,next(".") 似乎会首先跳过分隔符(默认情况下是空格)。也许这就是所期望的。如果不是,您需要使用 sc.delimiter() 来保存当前的分隔符模式,使用 sc.useDelimiter(??) 将其设置为不匹配任何内容的模式(也许是一个空模式,但我还没有测试过);然后使用 next(".");最后使用 sc.useDelimiter 来恢复先前的分隔符。 - ajb
5个回答

14
Scanner类的设计是为了读取以空格分隔的标记。它是一个方便的类,包装了底层输入流。在Scanner出现之前,你只能读取单个字节,如果你想读取单词或行,那就非常痛苦。使用Scanner时,你传入System.in,并进行多次read()操作来为你令牌化输入。读取单个字符是一种更基本的操作。 来源 你可以使用(char) System.in.read();。

可以使用,但是结果可能会相当混乱,因为Scanner将根据前面的Scanner API 调用预读(和缓冲)字符。 - Stephen C

4
根据javadoc的说明,Scanner不适用于读取单个字符。您需要将Scanner附加到InputStream(或其他内容)上,并由其解析输入。它还可以去除不需要的字符。因此,您可以轻松读取数字、行等内容。如果您只需要从输入中获取字符,请使用InputStreamReader等工具。

2
要得到一个明确的原因,您需要询问那个API的设计者。但是可能的一个原因是,(假设有一个)nextChar 的意图在扫描模型中并不适合很好地解决问题。
  • 如果 nextChar() 表现得像 Reader 上的 read() 一样,只需从扫描器返回下一个未使用字符,则它与其他 next<Type> 方法的行为不一致。这些方法在尝试解析值之前跳过分隔符字符。

  • 如果 nextChar() 表现得像 nextInt,则:

    • 跳过分隔符会对某些人来说是“意外”的;

    • 存在是否应该接受单个“原始”字符、代表 char 的数字序列或甚至支持转义等问题。1

无论他们做出什么选择,都会有人不满意。我的猜测是,设计者们决定远离陷阱。

1

Scanner类基于String的next(Pattern)方法实现逻辑。其他API方法,如nextDouble()nextFloat(),需要在其中提供模式。

然后description says类说:

一个简单的文本扫描器,可以使用正则表达式解析原始类型和字符串。

扫描仪使用定界符模式将其输入拆分为标记,默认情况下匹配空格。然后,可以使用各种next方法将结果标记转换为不同类型的值。

从描述中可以看出,有人忘记了char,因为它肯定是一种原始类型。

但是该类的概念是查找模式,而char没有模式,只是下一个字符。我认为这种逻辑导致没有实现nextChar。

如果您需要逐个字符读取文件,则可以使用更有效的类。


1
我想这可能与编码有关。一个char占用16字节,某些编码将使用一个字节来表示一个字符,而另一种编码则会使用两个或更多字节。当Java最初设计时,他们假设任何Unicode字符都适合2个字节,而现在Unicode字符可以需要多达4个字节(UTF-32)。Scanner没有办法用单个char表示UTF-32代码点。
您可以在构造实例时为Scanner指定编码,如果未提供,则将使用平台字符集。但是,这仍然无法处理3或4字节的Unicode字符的问题,因为它们无法表示为单个char基元(因为char仅为16字节)。因此,您最终会得到不一致的结果。

2
我不明白。如果Scanner无法检索字符,因为它无法确定编码方式,那么它如何实现_任何_扫描方法呢?毕竟,这些方法必须查看字符,不是吗? - ajb
你是不是指返回 String 类型的方法?问题在于,如果你有一个4字节的Unicode字符,如何用 char 来表示它?如果是 String,它可以在内部表示为一个带有两个 charchar 数组。但如果你要处理3或4字节的Unicode字符,就无法从 nextChar 中获得有意义的响应了。 - Vivin Paliath
据我所知,Reader 负责处理编码。请查看 http://docs.oracle.com/javase/1.5.0/docs/api/index.html?java/io/InputStream.html。 - Marc Hauptmann
@ajb 一个“字符”字符串仍然是由char[]内部组成的。如果您正在读取UTF-32字符,那么nextChar应该返回什么?如果它被编码为UTF-32,则String可以计算出每个字符需要4个字节(因为您可以将编码指定为String)。 - Vivin Paliath
@ajb,Java中的16位是由于历史上的错误而产生的;他们应该使用32位。Scanner内部使用一个CharBuffer,它在内部使用一个char[]数组。这正是我的观点:在Java中,你不能用单个char表示UTF-32,这可能就是为什么Scanner没有nextChar的原因。Readable将字节读入一个可以容纳多个charCharBuffer中,因此UTF-32代码点不是问题。nextChar的语义取决于编码。 - Vivin Paliath
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接