简体   繁体   English

Java 缓冲区读取器在 ctrl z 上崩溃

[英]Java bufferreader crashes on ctrl z

I'm making a game which plays until the user enters quit in the command line.我正在制作一个游戏,直到用户在命令行中输入退出为止。

The user can enter different commands like get and go, with the get command the user can say what to get like, get baseball bat.用户可以输入不同的命令,如 get 和 go,使用 get 命令,用户可以说要得到什么,得到棒球棒。 What I do in my code is split the command.我在代码中所做的是拆分命令。

everything is working fine but I have found a bug which I can't solve.一切正常,但我发现了一个我无法解决的错误。 If I enter "get" and press space and then ctrl + z it gets in a while loop which never ends.如果我输入“get”并按空格然后ctrl + z它会进入一个永远不会结束的 while 循环。

It only happens with ctrl + z (1 time with ctrl c but after that 1 time not anymore)它只在ctrl + z时发生(用ctrl c 1 次,但之后 1 次不再发生)

 private void run() 
{       
    while (! quitCommand)
    {
        
        String input = null;
        
        try 
        {   
            input = null;
            System.out.println("Input "+ input);
            System.out.println("Give a command.");
            BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
            input = is.readLine();
            handleCommand(input);
            // As long as the command isn’t to quit:
            // get the next input line and handle it. (With handleCommand.)
        } 
        
        catch (Exception e) 
        {
            System.out.println("Something went wrong we are sorry try again.");
            e.printStackTrace();
        }
        
    }
}

/**
* @param userInput (This is the entire input string from the user.)
*
* (Tell others to) Perform the task which belongs to the given
* command.
*/
private void handleCommand(String userInput) 
{
    
    
    // Split the user input string.
    if (userInput != null)          // user input can not be empty
    {
        String[] delenTekst = userInput.split(" ");
        
        // The first word is a command. The rest is extra information
        String command = delenTekst[0];
        String extra = "";
        
        for (int i = 1; i < delenTekst.length; i ++)
        {
            if (i == 1)
            {
                extra = extra + delenTekst[i];
            }
            else
            {
                extra = extra +" " + delenTekst[i];
            }               
        }

        switch (command)
        {
            // Check if the command is to travel between rooms. If so, handle
            case "go"
            : 
                this.checkRoomTravel(extra);
                break;
            // If there isn't any room travel, then check all other command
            case "get"
            :   
                System.out.println("Looking for " +extra );
                this.handleGetCommand(extra);
                break;
            case "quit"
            :
                quitCommand = true;
                break;
            default
            :
                System.out.println("Command is not known try help for information");
                break;  
        }
    }
    else
    {
        userInput = "help";
    }
}

I'm new to java so it can be something really simple.我是 Java 新手,所以它可能非常简单。

On the top of my script I have a private boolean quitCommand = false;在我的脚本顶部,我有一个私有的布尔值quitCommand = false; which is to check if the user entered quit.这是检查用户是否输入退出。

Ctrl + Z closes the Console and therefore your readLine() returns null as pretended to indicate that end of file was reached. Ctrl + Z关闭控制台,因此您的readLine()返回 null 假装表示已到达文件末尾。 So all you need to do, is to check for null returned by readLine() and handle this as you handle the "quit".所以你需要做的就是检查readLine()返回的null并在你处理“退出”时处理它。

I've changed your code (just to test my thesis) and also stream lined a few things, eg you dont need to recreate a BufferedReader every time you read a line.我已经改变了你的代码(只是为了测试我的论文)并且还流线了一些东西,例如你不需要在每次阅读一行时重新创建一个BufferedReader

private boolean quitCommand = false;
 private void runIt() {       
     BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
     String input = null;

     while(!quitCommand) {
         try {   
             System.out.print("Give a command: ");
             input = is.readLine();

             // As long as the command isn’t to quit:
             if(input == null || "quit".equals(input.trim())) quitCommand = true;
             if(quitCommand) break;

             // get the next input line and handle it. (With handleCommand.)
             String[] words = input.trim().split("\\s+");

             // ** This is the original handleCommand line **
             System.out.println(input + ":" + Arrays.toString(words));
         } 
         catch (Exception e) {
             System.out.println("Something went wrong we are sorry try again.");
             e.printStackTrace();
         }
     }
 }

BTW: To split the input into words I'd use the regular expression as shown in my code.顺便说一句:要将输入拆分为单词,我将使用正则表达式,如我的代码所示。 This works also if the user enters tabs or multiple spaces.如果用户输入制表符或多个空格,这也适用。

On DOS/Windows Ctrl + Z means end of input.在 DOS/Windows 上Ctrl + Z表示输入结束。 This causes readLine() to return null no matter how many times you call it.无论您调用多少次,这都会导致 readLine() 返回null This is likely to cause your code to fail as you don't appear to check for it.这很可能会导致您的代码失败,因为您似乎没有检查它。 I suspect you are getting a NullPointerException which you are pretending didn't happen and trying again, endlessly.我怀疑你得到了一个 NullPointerException 你假装没有发生并无休止地重试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM