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 "
换行符处理 作为分隔符跳过 作为行结束符消耗
相关推荐
come112342 小时前
深入Spring Boot的核心——配置管理(指南四)
java·spring boot·后端
武昌库里写JAVA3 小时前
Java 设计模式在 Spring 框架中的实践:工厂模式与单例模式
java·vue.js·spring boot·sql·学习
麦兜*3 小时前
Redis高可用架构设计:主从复制、哨兵、Cluster集群模式深度对比
java·数据库·spring boot·redis·spring·spring cloud·缓存
王嘉俊9253 小时前
Redis 入门:高效缓存与数据存储的利器
java·数据库·redis·后端·spring·缓存·springboot
王维3 小时前
【shardingsphere-jdbc】分表实践
java·数据库
道可到4 小时前
淘宝面试原题 Java 面试通关笔记 02|从编译到运行——Java 背后的计算模型(面试可复述版)
java·后端·面试
DKPT4 小时前
JVM如何管理直接内存?
java·笔记·学习
SimonKing4 小时前
GitHub 标星 370k!免费编程资源大合集,从此自学不花一分钱
java·后端·程序员
kfepiza4 小时前
Java的任务调度框架之Quartz 笔记250930
java·java ee