企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## [扫描输入](https://lingcoder.gitee.io/onjava8/#/book/18-Strings?id=%e6%89%ab%e6%8f%8f%e8%be%93%e5%85%a5) 到目前为止,从文件或标准输入读取数据还是一件相当痛苦的事情。一般的解决办法就是读入一行文本,对其进行分词,然后使用`Integer`、`Double`等类的各种解析方法来解析数据: ~~~ // strings/SimpleRead.java import java.io.*; public class SimpleRead { public static BufferedReader input = new BufferedReader(new StringReader( "Sir Robin of Camelot\n22 1.61803")); public static void main(String[] args) { try { System.out.println("What is your name?"); String name = input.readLine(); System.out.println(name); System.out.println("How old are you? " + "What is your favorite double?"); System.out.println("(input: <age> <double>)"); String numbers = input.readLine(); System.out.println(numbers); String[] numArray = numbers.split(" "); int age = Integer.parseInt(numArray[0]); double favorite = Double.parseDouble(numArray[1]); System.out.format("Hi %s.%n", name); System.out.format("In 5 years you will be %d.%n", age + 5); System.out.format("My favorite double is %f.", favorite / 2); } catch(IOException e) { System.err.println("I/O exception"); } } } /* Output: What is your name? Sir Robin of Camelot How old are you? What is your favorite double? (input: <age> <double>) 22 1.61803 Hi Sir Robin of Camelot. In 5 years you will be 27. My favorite double is 0.809015. */ ~~~ `input`字段使用的类来自`java.io`,[附录:流式 I/O](https://lingcoder.gitee.io/onjava8/#/./Appendix-IO-Streams)详细介绍了相关内容。`StringReader`将`String`转化为可读的流对象,然后用这个对象来构造`BufferedReader`对象,因为我们要使用`BufferedReader`的`readLine()`方法。最终,我们可以使用`input`对象一次读取一行文本,就像从控制台读入标准输入一样。 `readLine()`方法将一行输入转为`String`对象。如果每一行数据正好对应一个输入值,那这个方法也还可行。但是,如果两个输入值在同一行中,事情就不好办了,我们必须分解这个行,才能分别解析所需的输入值。在这个例子中,分解的操作发生在创建`numArray`时。 终于,Java SE5 新增了`Scanner`类,它可以大大减轻扫描输入的工作负担: ~~~ // strings/BetterRead.java import java.util.*; public class BetterRead { public static void main(String[] args) { Scanner stdin = new Scanner(SimpleRead.input); System.out.println("What is your name?"); String name = stdin.nextLine(); System.out.println(name); System.out.println( "How old are you? What is your favorite double?"); System.out.println("(input: <age> <double>)"); int age = stdin.nextInt(); double favorite = stdin.nextDouble(); System.out.println(age); System.out.println(favorite); System.out.format("Hi %s.%n", name); System.out.format("In 5 years you will be %d.%n", age + 5); System.out.format("My favorite double is %f.", favorite / 2); } } /* Output: What is your name? Sir Robin of Camelot How old are you? What is your favorite double? (input: <age> <double>) 22 1.61803 Hi Sir Robin of Camelot. In 5 years you will be 27. My favorite double is 0.809015. */ ~~~ `Scanner`的构造器可以接收任意类型的输入对象,包括`File`、`InputStream`、`String`或者像此例中的`Readable`实现类。`Readable`是 Java SE5 中新加入的一个接口,表示“具有`read()`方法的某种东西”。上一个例子中的`BufferedReader`也归于这一类。 有了`Scanner`,所有的输入、分词、以及解析的操作都隐藏在不同类型的`next`方法中。普通的`next()`方法返回下一个`String`。所有的基本类型(除`char`之外)都有对应的`next`方法,包括`BigDecimal`和`BigInteger`。所有的 next 方法,只有在找到一个完整的分词之后才会返回。`Scanner`还有相应的`hasNext`方法,用以判断下一个输入分词是否是所需的类型,如果是则返回`true`。 在`BetterRead.java`中没有用`try`区块捕获`IOException`。因为,`Scanner`有一个假设,在输入结束时会抛出`IOException`,所以`Scanner`会把`IOException`吞掉。不过,通过`ioException()`方法,你可以找到最近发生的异常,因此,你可以在必要时检查它。