Java-Scanner类讲解

Java Scanner 类

Scanner类是Java中一个非常使用的工具类,位于java.util包中,主要用于解析基本类型和字符串的简单文本扫描器。接下来会进行详细讲解,若有不足,欢迎提出!!!

一、Scanner类概述

Scanner类可以讲输入(通常是文件或键盘输入)分解为标记(Tokens),然后使用各种next方法将这些标记转换为不同类型的值。它使用正则表达式来解析基本类型和字符串。

核心功能

  • 多输入源支持:支持控制台、文件、字符串、输入流等多种输入源;
  • 数据类型解析:能将输入解析为各种基本类型和字符串;
  • 正则表达式支持:可以使用正则表达式进行模式匹配和分隔;
  • 本地化支持:支持不同地区的数据格式;
  • 输入验证:提供hasNext系列方法进行输入验证。

二、创建Scanner对象

Scanner有多个构造函数,可以从不同的数据来源读取数据。

  • 从标准输入读取;
  • 从字符串读取;
  • 从文件读取(需要处理IOException);
  • 从输入流创建;
  • 从Readable对象创建。

更多的是使用方法一和方法三。

java 复制代码
// 1. 从标准输入创建
Scanner stdinScanner = new Scanner(System.in);

// 2. 从字符串创建
Scanner stringScanner = new Scanner("Text 123 45.67");

// 3. 从文件创建(需处理异常)
try {
    Scanner fileScanner = new Scanner(new File("data.txt"));
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

// 4. 从输入流创建
Scanner streamScanner = new Scanner(inputStream);

// 5. 从Readable对象创建
Scanner readableScanner = new Scanner(readableObject);

进行配置

java 复制代码
// 设置分隔符(支持正则表达式)
scanner.useDelimiter(","); // 简单分隔符
scanner.useDelimiter("\\s*,\\s*"); // 允许分隔符前后有空格

// 设置区域(影响数字解析格式)
scanner.useLocale(Locale.US); // 使用点作为小数点
scanner.useLocale(Locale.FRENCH); // 使用逗号作为小数点

// 设置基数(用于数字解析)
scanner.useRadix(16); // 设置为16进制模式

三、数据读取方法

方法类型 包含方法 说明
整数类型 nextByte(), nextShort(), nextInt(), nextLong() 读取各种整数
浮点类型 nextFloat(), nextDouble() 读取浮点数
大数类型 nextBigInteger(), nextBigDecimal() 读取大数
布尔类型 nextBoolean() 读取布尔值
字符串类型 next(), nextLine() 读取字符串

关键区别点

  1. 输入消耗行为
    • 跳过前导的分隔符(默认是空白字符);
    • 跳过匹配目标类型的内容;
    • 不会消耗后面的分隔符。

特殊案例:

  • nextLine() 会读取直到行尾并消耗换行符;
  • 其余的方法读取后,后面如果跟nextLine()会读到空行
java 复制代码
Scanner scanner = new Scanner("123\n456");
int num = scanner.nextInt();  // 读取123,不消耗\n
String line = scanner.nextLine();  // 读取空字符串(因为读取了\n)

3.1 整数读取

方法 返回类型 取值范围 基数支持 特点
nextByte() byte -128 ~ 127 支持 读取字节型整数
nextShort() short -32768 ~ 32767 支持 读取短整型
nextInt() int -2³¹ ~ 2³¹-1 支持 最常用的整数读取方法
nextLong() long -2⁶³ ~ 2⁶³-1 支持 读取长整型
1. nextInt() - 最常用的整数读取方法

功能: 读取一个32位有符号整数。 示例:

java 复制代码
Scanner scanner = new Scanner(System.in);
System.out.print("请输入一个整数: ");
int number = scanner.nextInt();
System.out.println("您输入的数是: " + number);

特点

  • 默认解析十进制数字;
  • 遇到非数字字符时停止读取;
  • 会跳过前导空白字符;
  • 不消耗数字后面的分隔符。

注意事项

java 复制代码
// 问题代码示例
int a = scanner.nextInt();
int b = scanner.nextInt();
// 如果输入"123 456"可以正常工作
// 但如果输入"123,456"会抛出InputMismatchException

// 解决方案:设置正确分隔符
scanner.useDelimiter(",");
2. nextLong()

功能:读取64位有符号长整数

使用场景:

  • 需要读取超过21亿的数字时;
  • 处理大ID号、时间戳等。
java 复制代码
System.out.print("请输入长整型ID: ");
long id = scanner.nextLong();
System.out.println("ID是: " + id);
3. nextByte() & nextShort() - 读取小范围整数

使用场景:

  • 明确知道输入数字范围较小时;
  • 需要自动范围检查时。

示例

java 复制代码
System.out.print("请输入年龄(0-127): ");
byte age = scanner.nextByte(); // 自动检查范围

特点

  • 如果输入超出类型范围,抛出InputMismatchException
  • 适合读取配置参数等小范围数字。

3.2 浮点类型

方法 返回类型 存储大小 精度 取值范围 特点
nextFloat() float 32位 6-7位有效数字 ±1.4E-45 ~ ±3.4E+38 读取单精度浮点数
nextDouble() double 64位 15-16位有效数字 ±4.9E-324 ~ ±1.8E+308 读取双精度浮点数(默认推荐)

基本使用示例

java 复制代码
Scanner scanner = new Scanner(System.in);

// 读取单精度浮点数
System.out.print("请输入浮点数(float): ");
float fValue = scanner.nextFloat();

// 读取双精度浮点数
System.out.print("请输入浮点数(double): ");
double dValue = scanner.nextDouble();

System.out.println("读取结果: float=" + fValue + ", double=" + dValue);

3.3 大数类型

1. nextBigImteger()方法

功能说明:

读取输入中的下一个标记(token)并将其转换为BigInteger对象。BigInteger可以表示任意精度的整数,适用于超出long类型范围的超大整数。

注意事项

  1. 输入必须是一个有效的整数表示
  2. 可以处理任意长度的整数(只要内存允许)
  3. 如果输入不是有效的整数格式,会抛出InputMismatchException
  4. 建议先使用hasNextBigInteger()进行检查
  5. 默认使用十进制,可以通过参数指定其他进制
java 复制代码
import java.util.Scanner;
import java.math.BigInteger;

public class BigIntegerExample {
    public static void main(String[] args) {
        // 示例1:基本用法
        Scanner scanner1 = new Scanner("12345678901234567890");
        BigInteger bigInt1 = scanner1.nextBigInteger();
        System.out.println("十进制大整数: " + bigInt1);
        
        // 示例2:指定进制
        Scanner scanner2 = new Scanner("FF");
        BigInteger bigInt2 = scanner2.nextBigInteger(16); // 16进制
        System.out.println("十六进制FF转为十进制: " + bigInt2);
        
        // 示例3:超大整数运算
        Scanner scanner3 = new Scanner("9999999999999999999999999999999999999999");
        BigInteger a = scanner3.nextBigInteger();
        BigInteger b = new BigInteger("1111111111111111111111111111111111111111");
        System.out.println("a + b = " + a.add(b));
    }
}
2. nextBigDecimal()方法

功能说明

读取输入中的下一个标记(token)并将其转换为BigDecimal对象。BigDecimal可以表示任意精度的十进制数,适用于需要高精度计算的场景,如金融计算。

注意事项:

  1. 输入必须是一个有效的十进制数表示(可以包含小数点)
  2. 可以处理任意精度的十进制数
  3. 如果输入不是有效的数字格式,会抛出InputMismatchException
  4. 建议先使用hasNextBigDecimal()进行检查
  5. 特别适合金融计算等需要精确小数运算的场景
java 复制代码
import java.util.Scanner;
import java.math.BigDecimal;

public class BigDecimalExample {
    public static void main(String[] args) {
        // 示例1:基本用法
        Scanner scanner1 = new Scanner("1234567890.1234567890");
        BigDecimal bigDec1 = scanner1.nextBigDecimal();
        System.out.println("高精度小数: " + bigDec1);
        
        // 示例2:精确计算
        Scanner scanner2 = new Scanner("0.1");
        BigDecimal a = scanner2.nextBigDecimal();
        BigDecimal b = new BigDecimal("0.2");
        System.out.println("0.1 + 0.2 = " + a.add(b)); // 输出0.3,而非浮点数的近似值
        
        // 示例3:金融计算
        Scanner scanner3 = new Scanner("10000000000.0000000001");
        BigDecimal principal = scanner3.nextBigDecimal();
        BigDecimal rate = new BigDecimal("0.05"); // 5%利率
        BigDecimal interest = principal.multiply(rate);
        System.out.println("利息: " + interest);
    }
}

相关检查方法 hasNextBigInteger()

  • 检查洗一个标记是否可以解释为BigInteger
  • 有重载方法可以指定进制:hasNextBigInteger(int radix) 示例:
java 复制代码
Scanner scanner = new Scanner("12345678901234567890");
if(scanner.hasNextBigInteger()) {
    BigInteger num = scanner.nextBigInteger();
}

hasNextBigDecimal()

  • 检查下一个标记是否可以解释为BigDecimal 示例:
java 复制代码
Scanner scanner = new Scanner("123.456789");
if(scanner.hasNextBigDecimal()) {
    BigDecimal num = scanner.nextBigDecimal();
}

综合示例:

java 复制代码
import java.util.Scanner;
import java.math.BigInteger;
import java.math.BigDecimal;

public class BigNumberDemo {
    public static void main(String[] args) {
        String input = "987654321098765432109876543210 3.141592653589793238462643383279";
        
        try (Scanner scanner = new Scanner(input)) {
            // 读取超大整数
            if (scanner.hasNextBigInteger()) {
                BigInteger hugeInt = scanner.nextBigInteger();
                System.out.println("超大整数: " + hugeInt);
                System.out.println("平方: " + hugeInt.pow(2));
            }
            
            // 读取高精度小数
            if (scanner.hasNextBigDecimal()) {
                BigDecimal pi = scanner.nextBigDecimal();
                System.out.println("圆周率近似值: " + pi);
                System.out.println("乘以2: " + pi.multiply(new BigDecimal("2")));
            }
        }
    }
}

使用场景建议

  1. nextBigInteger()适用场景:

    • 处理超过long范围的整数(大于2^63-1或小于-2^63)
    • 加密算法中的大数运算
    • 需要精确整数计算的场合
  2. nextBigDecimal()适用场景:

    • 金融计算(货币、利率等)
    • 科学计算需要高精度小数的场合
    • 避免浮点数精度问题的任何计算
  3. 性能考虑

    • BigInteger/BigDecimal比基本类型慢
    • 只在必要时使用
    • 对于已知范围内的数,优先使用基本类型
  4. 异常处理

    • 总是检查hasNext...()方法
    • 捕获可能的InputMismatchException
    • 使用try-with-resources确保Scanner关闭

3.4 布尔类型

nextBoolean()方法
  1. 方法功能

Boolean()是Scanner类的一个实例方法,用于从输入源读取下一个标记(token)并将其解析为boolean值。

核心功能:

  • 读取输入中的下一个有效标记;
  • 将其转换为boolean值;
  • 返回转换后的boolean值。
  1. 返回值:

返回解析后的boolean值:

  • 当输入为"true"(不区分大小写)时返回true
  • 当输入为"false"(不区分大小写)时返回false
  1. 工作原理:

    1. 首先跳过输入中的任何前导空白字符
    2. 读取下一个完整的标记(token)
    3. 将标记与"true"和"false"比较(不区分大小写)
    4. 返回匹配的boolean值
  2. 注意事项

    4.1 有效输入格式:

  • 接受的值​:

    • "true"(任何大小写组合,如True、TRUE、tRuE)
    • "false"(任何大小写组合,如False、FALSE、fAlSe)
  • 不接受的值​:

    • 任何其他字符串(包括"1"/"0"、"yes"/"no"等)
    • 空字符串或空白字符

    4.2 异常情况:

  • InputMismatchException​:当下一个标记不能转换为boolean值时抛出

  • IllegalStateException​:当Scanner已关闭时调用此方法

  • NoSuchElementException​:当输入已耗尽时调用此方法

    4.3 最佳实践

    • 总是先使用hasNextBoolean()进行检查
    • 处理可能的异常
    • 考虑用户输入的各种情况(大小写、前后空格等)

示例:

java 复制代码
Scanner scanner = new Scanner("true false TRUE False tRuE fAlSe");
while(scanner.hasNextBoolean()) {
    System.out.println(scanner.nextBoolean());
}
// 输出:
// true
// false
// true
// false
// true
// false

3.5 字符串类型

1.next()方法

1.1 方法功能 next()方法用于从输入源读取并返回下一个完整的标记(token),默认以空白字符作为分隔符。

1.2 工作原理

  1. 跳过输入中的前导空白字符(空格、制表符、换行符等)
  2. 读取字符直到遇到下一个分隔符(默认是空白字符)
  3. 返回读取到的字符串(不包含分隔符)

1.3 重要特性

  • 分隔符 :默认使用空白字符(\s+)作为分隔符
  • 阻塞行为:当从System.in读取时,如果没有输入会阻塞等待
  • 标记边界:遇到分隔符即停止读取
  • 大小写敏感:保留原始大小写

示例:

java 复制代码
Scanner scanner = new Scanner("Hello World!\nJava Scanner");
System.out.println(scanner.next()); // 输出: Hello
System.out.println(scanner.next()); // 输出: World!
System.out.println(scanner.next()); // 输出: Java

1.6 注意事项

  1. 输入等待:从控制台读取时会阻塞等待用户输入;
  2. 异常情况:
    • NoSuchElementException:输入已耗尽时抛出
    • IllegalStateException:Scanner已关闭时抛出
  3. 分隔符处理:不会包含分隔符在返回值中;
  4. 前导空白:不会跳过前导空白字符。

1.7 典型应用场景

  • 读取以空格分隔的单词
  • 处理结构化的文本数据
  • 需要逐个标记处理的输入
2. nextLine()方法

2.1 方法功能 nextLine()方法读取从当前位置到行尾的所有字符(包括空格但不包括最后的换行符),返回一个字符串

2.2 工作原理

  1. 从当前位置开始读取
  2. 包含所有字符直到遇到行终止符(\n\r\r\n)
  3. 返回读取到的字符串(不包含行终止符)
  4. 将Scanner位置移动到下一行开头

2.3 重要特性

  • 行终止符:识别各种系统的行结束符
  • 内容包含:读取包括空格在内的所有字符
  • 位置移动:读取后位置移动到下一行开头
  • 空行处理:可以返回空字符串("")

示例:

java 复制代码
Scanner scanner = new Scanner("第一行文本\n第二行文本\n\n第四行文本");
System.out.println("[" + scanner.nextLine() + "]"); // [第一行文本]
System.out.println("[" + scanner.nextLine() + "]"); // [第二行文本]
System.out.println("[" + scanner.nextLine() + "]"); // [] (空行)
System.out.println("[" + scanner.nextLine() + "]"); // [第四行文本]

2.4 注意事项

  1. 换行符处理:消耗但不包含行终止符
  2. 混合使用问题 :与next()系列方法混用需谨慎
  3. 空行返回:会返回空字符串而非null
  4. 控制台输入:从控制台读取时会阻塞等待用户输入回车

2.5 典型应用场景

  • 读取用户输入的整行文本
  • 处理包含空格的完整句子
  • 读取配置文件中的整行内容
  • 处理多行文本数据
next() VS nextLine()
特性 next() nextLine()
读取单位 标记(token) 整行
分隔符 空白字符 行终止符
包含空格
前导空白处理 自动跳过 保留
典型返回值 "Hello" "Hello World"
输入" a b "的结果 "a" (两次调用得到"a"和"b") " a b "
换行符处理 作为分隔符跳过 作为行结束符消耗
相关推荐
四谎真好看1 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程1 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t1 小时前
ZIP工具类
java·zip
lang201509282 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan2 小时前
第10章 Maven
java·maven
百锦再3 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说3 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多3 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再3 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父4 小时前
Spring—注解开发
java·后端·spring