You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关闭Scanner后Java程序报错,BPM转毫秒工具故障排查

问题分析与解决

问题根源

你遇到的“no line found”错误,核心原因是关闭Scanner时会连带关闭底层的System.in输入流:

  • 在ms_calc()中调用scanbpm.close()后,System.in被永久关闭。
  • 随后你调用main(null)再次执行ms_calc(),新创建的Scanner scanbpm = new Scanner(System.in)试图读取已经关闭的输入流,直接触发NoSuchElementException。
  • 另外你的get_user_int方法里的finally块每次都调用scan.nextLine(),如果用户输入有效整数后,nextInt()只会读取数字,剩下的换行符会被nextLine()消费,这个逻辑本身没问题,但配合输入流关闭的问题会直接引发报错。

修复方案

1. 避免递归调用main(null),改用循环结构

不要通过重复调用main方法实现程序循环,改用while循环控制程序的运行状态。

2. 只创建一次Scanner,全程复用

把Scanner的创建放在循环外部,直到程序结束时再关闭,避免重复关闭System.in输入流。

修改后的代码示例

import java.util.Scanner;

public class BpmToMsConverter {
    public static void main(String[] args) {
        Scanner scanbpm = new Scanner(System.in);
        boolean keepRunning = true;
        
        while (keepRunning) {
            ms_calc(scanbpm);
            
            // 询问用户是否继续计算
            System.out.println("是否继续计算?(输入y继续,其他键退出)");
            String choice = scanbpm.nextLine().trim();
            if (!choice.equalsIgnoreCase("y")) {
                keepRunning = false;
            }
        }
        
        scanbpm.close(); // 程序结束时统一关闭Scanner
    }

    public static void ms_calc(Scanner scanbpm) {
        System.out.println("What is your BPM?");
        int bpm = get_user_int(scanbpm, 1, 2300);
        
        // BPM转毫秒计算逻辑
        double mS1 = Math.round((bpm * 100.0) / 6) * 4;  
        double mS2 = Math.round((bpm * 100.0) / 6) * 2; 
        int mS1R = (int) mS1;
        int mS2R = (int) mS2;
        
        System.out.println("____________________________________");
        System.out.println();
        System.out.println("Whole : " + mS1R + " ms");
        System.out.println();
        System.out.println("1/2 : " + mS2R + " ms");
        
        for (int X = 1; X < 9; X = X * 2) {
            double mS = Math.round((60000.00 / X) / bpm);
            int Y = X * 4;
            int mSR = (int) mS;
            System.out.println();
            System.out.println("1/" + Y + " : " + mSR + " ms");
        }
    
        System.out.println("____________________________________");
        System.out.println();
    }
    
    public static int get_user_int(Scanner scan, int min, int max) {
        int user_input = min - 1;        
        boolean keep_asking = true;
        
        while (keep_asking || user_input < min || user_input > max) { 
            try {
                user_input = scan.nextInt();
                keep_asking = false;
                
                // 验证输入范围,不合法则重新提示
                if (user_input < min || user_input > max) {
                    System.out.println("输入超出范围,请输入" + min + "到" + max + "之间的整数");
                    keep_asking = true;
                }
            } catch (Exception e) { 
                System.out.println("Invalid input. 请输入整数");
                scan.nextLine(); // 消费无效输入的剩余内容
                keep_asking = true;
            }
        }
        
        scan.nextLine(); // 消费输入整数后的换行符,避免影响后续输入
        System.out.println(user_input);
        return user_input;
    }
}

额外优化点

  • 原计算逻辑中的(bpm*100)/6改为(bpm * 100.0)/6,避免整数除法导致的精度丢失。
  • 在get_user_int中增加了范围验证的提示,让用户更清楚错误原因。
  • 移除了finally块中的scan.nextLine(),改为在有效输入后针对性消费换行符,避免不必要的输入干扰。

内容的提问来源于stack exchange,提问作者Rivera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:30:52