如何在java中处理空的扫描仪输入字符串?

How to handle empty scanner input strings in java?

提问人:daniirp 提问时间:7/28/2021 更新时间:7/29/2021 访问量:914

问:

我正在开发一个.xml文件生成器。它的工作原理是要求用户输入 5 个不同的值,然后使用它们来生成.xml数据容器。这是代码:

public class Generator {
public static void main(String[] args) throws InterruptedException {
    Scanner reader = new Scanner(System.in);
    while (true) {

        System.out.println("Input the furni ID (input only numbers here).");
        String furniID = reader.nextLine();

        System.out.println("Input the furni's file name (without '.swf'. You can input numbers, letters and underscores here).");
        String furniFileName = reader.nextLine();

        System.out.println("Input the furni's revision (input only numbers here).");
        String furniRevision = reader.nextLine();

        System.out.println("Input the furni's name (this will be the name that it will display when you click on the furni in a room or in your inventory).");
        String furniName = reader.nextLine();

        System.out.println("Input the furni's description (this will be displayed under the furni's name).");
        String furniDescription = reader.nextLine();

        System.out.println("Input the furni's furniline. This is just a name for a group of furnis that belong to the same collection. For example you can input 'custom' (without quotation marks).");
        String furniLine = reader.nextLine();

        System.out.println("Generating your furnidata...");
        System.out.println(" ");

        TimeUnit.SECONDS.sleep(1);

        System.out.println("<furnitype id=\"" + furniID + "\"" + " classname=\"" + furniFileName + "\"" + ">");
        System.out.println("<revision>" + furniRevision + "</revision>");
        System.out.println("<xdim>1</xdim>");
        System.out.println("<ydim>1</ydim>");
        System.out.println("</partcolors>");
        System.out.println("<name>" + furniName + "</name>");
        System.out.println("<description>" + furniDescription + "</description>");
        System.out.println("</adurl");
        System.out.println("<offerid>-1</offerid>");
        System.out.println("<buyout>0</buyout>");
        System.out.println("<rentofferid>-1</rentofferid>");
        System.out.println("<rentbuyout>0</rentbuyout>");
        System.out.println("<bc>0</bc>");
        System.out.println("<excludeddynamic>0</excludeddynamic>");
        System.out.println("<customparams/>");
        System.out.println("<specialtype>1</specialtype>");
        System.out.println("<canstandon>0</canstandon>");
        System.out.println("<cansiton>0</cansiton>");
        System.out.println("<canlayon>0</canlayon>");
        System.out.println("<furniline>" + furniLine + "</furniline>");
        System.out.println("</furnitype>");
        System.out.println(" ");

        System.out.println("Do you want to generate another furnidata? (YES/NO)");
        String confirmation = reader.nextLine();

        if (confirmation.equals("NO")) {
            System.out.println("Furnidata generator has been stopped.");
            break;
        } else if (confirmation.equals("no")) {
            System.out.println("Furnidata generator has been stopped.");
            break;
        } else if (confirmation.equals("No")) {
            System.out.println("Furnidata generator has been stopped.");
            break;
        }
    }
}

我希望程序通过按没有书面文本的回车键来检测某人何时输入空字符串,并打印一条消息,要求用户不要输入空字符串。我尝试使用 try-catch 语句执行此操作,但是在打印消息后,程序会执行下一行,而不是重新执行用户输入空字符串的行。我怎样才能做到这一点?

异常 java.util.scanner

评论

0赞 rzwitserloot 7/28/2021
.readLine()如果提供空行,则返回空字符串。 例如,会检测到这一点。无需在这里涉及尝试/捕捉。if (furniLine.isEmpty())
0赞 Seelenvirtuose 7/28/2021
如果您希望只要用户提供空输入,就会提示他输入,则可以使用 do-while-loop 来执行此操作。
0赞 daniirp 7/28/2021
@Seelenvirtuose好吧,我知道 do-while 循环是如何工作的,但我是初学者。如何使“输入字符串不为空”成为语句的条件?while

答:

-1赞 Shailesh Suryawanshi 7/28/2021 #1

您可能想要使用。

 String furniID = reader.nextLine();
 furniID = furniID.trim();
 if(furniID.equals("")){
     System.out.println("Empty Here. ");
 }

正如评论中所建议的那样,如果您提供空行或直接按回车键,则返回一个空字符串。.readLine()

上面的正则表达式将处理空字符串或用户可能输入的字符串。""whitespaces

编辑 1正如评论中所建议的那样,正则表达式在这里可能有点矫枉过正。string.trim() 将处理制表符、尾随前导空格和空字符串。

评论

0赞 Shailesh Suryawanshi 7/29/2021
我同意。在这里使用正则表达式可能有点矫枉过正。将相应地更改答案。
0赞 DevilsHnd - 退した 7/29/2021 #2

每当您提示用户提供特定数据时,您都应该验证输入的数据,如果数据不正确,请允许用户重试,以免由于某种可以避免的错误而停止应用程序。对于这种事情,使用正则表达式(正则表达式)是没有问题的

用户不输入任何内容(只需按键)只是一个问题。在某些提示下,您期望用户仅输入数字。String#matches() 方法中的小正则表达式是理想的选择,例如:ENTER

if (!userInput.matches("\\d+") {
   System.out.println("Invalid input! Numerical digits only!");
}

如果用户输入所有数字不匹配,则显示“无效输入!

每个提示都应该在自己的 or 循环中,以便可以完成验证,并且用户有机会重新输入数据。如果您有很多提示,则可以创建一个类方法来处理所有这些提示,以删除重复的编码。例如,下面修改了您的代码,以便名为 askUser() 的方法可以处理对用户的提示:dowhile

public class Generator {

    public static void main(String[] args) {
        java.util.Scanner reader = new java.util.Scanner(System.in);
        while (true) {
            // Only a String repesentation of numerical digits will be accepted. 
            // 1 to 20 digits are acceptable)
            String furniID = askUser(reader, "Input the furni ID (input only numbers here).", 
                    "\\d{1,20}");

            /* Only characters A to Z in either upper or lower case, digits 
               from 0 to 9, whitespaces, and underscores will be accepted 
               within the Users input. The period (.) is not acceptable 
               therefore eliminating the possibility of a file name extension
               like .swf to be applied to the supplied file name. File name can 
               be 1 to 80 characters.                               */
            String furniFileName = askUser(reader, "Input the furni's file name (without "
                    + "'.swf'.\nYou can input numbers, letters and underscores here).", 
                    "(?i)[a-z0-9 _]{1,80}");
            
            // Only a String repesentation of numerical digits will be accepted. 
            // 1 to 20 digits are acceptable)
            String furniRevision = askUser(reader, "Input the furni's revision (input "
                    + "only numbers here).", "\\d{1,20}");
            
            /* Only characters A to Z in either upper or lower case, digits 
               from 0 to 9, whitespaces, and underscores will be accepted 
               within the Users input. The period (.) is not acceptable. The
               name can be 1 to 25 characters in length.                  */
            String furniName = askUser(reader, "Input the furni's name (this will be "
                    + "the name that will\nbe displayed when you click on the furni in "
                    + "a room or in\nyour inventory).", "(?i)[a-z0-9 _]{1,25}");

            /* Only characters A to Z in either upper or lower case, digits 
               from 0 to 9, whitespaces, and periods will be accepted within 
               the Users input. Description can be a minimum of 5 to a maximum 
               of 120 characters in length.  */
            String furniDescription = askUser(reader, "Input the furni's description ("
                    + "this will be displayed\nunder the furni's name).", "(?i)[a-z0-9. ]{5,120}");

            /* Only characters A to Z in either upper or lower case, digits 
               from 0 to 9, and whitespaces will be accepted within the Users 
               input. The period (.) is not acceptable. The furniline name can 
               be 1 to 25 characters in length.                      */   
            String furniLine = askUser(reader, "Input the furni's furniline. This is just "
                    + "a name for a\ngroup of furnis that belong to the same collection. "
                    + "For\nexample you can input 'custom' (without quotation marks).", 
                    "(?i)[a-z0-9 ]{1,25}");

            System.out.println("Generating your furnidata...");
            System.out.println(" ");
            System.out.println("<furnitype id=\"" + furniID + "\"" + " classname=\"" + furniFileName + "\"" + ">");
            System.out.println("<revision>" + furniRevision + "</revision>");
            System.out.println("<xdim>1</xdim>");
            System.out.println("<ydim>1</ydim>");
            System.out.println("</partcolors>");
            System.out.println("<name>" + furniName + "</name>");
            System.out.println("<description>" + furniDescription + "</description>");
            System.out.println("</adurl");
            System.out.println("<offerid>-1</offerid>");
            System.out.println("<buyout>0</buyout>");
            System.out.println("<rentofferid>-1</rentofferid>");
            System.out.println("<rentbuyout>0</rentbuyout>");
            System.out.println("<bc>0</bc>");
            System.out.println("<excludeddynamic>0</excludeddynamic>");
            System.out.println("<customparams/>");
            System.out.println("<specialtype>1</specialtype>");
            System.out.println("<canstandon>0</canstandon>");
            System.out.println("<cansiton>0</cansiton>");
            System.out.println("<canlayon>0</canlayon>");
            System.out.println("<furniline>" + furniLine + "</furniline>");
            System.out.println("</furnitype>");
            System.out.println(" ");

            // Only y or n can be supplied in any letter case. 
            // Anything else generates an Invalid Input message.
            String confirmation = askUser(reader, "Do you want to generate another furnidata? (y/n)", 
                    "(?i)[yn]", "Invalid Choice! Either 'y' for Yes or 'n' for No!");
            if (confirmation.equalsIgnoreCase("n")) {
                System.out.println("Furnidata generator has been stopped.");
                break;
            }
        }
    }
    
    /**
     * Displays the supplied prompt within the Console Window and permits the User 
     * to enter a response. User input is validated based on the regex argument 
     * supplied to the <b>validationRegEx</b> parameter.<br><br>
     * 
     * @param inputReader (Scanner) Scanner object to use for User Input.<br>
     * 
     * @param promptString (String) The prompt to display within the console window.<br>
     * 
     * @param validationRegEx (String) A regular expression that will be used 
     * within a <b>String#matches()</b> method to validate the User's input.<br>
     * 
     * @param errorString (Optional - String) Default validation error message is:<pre>
     * 
     *     "Invalid input! Try again..."</pre><br>
     * 
     * Here you can optionally supply your own message for non-valid entries.<br>
     * 
     * @return (String) The valid response from User.
     */
    public static String askUser(java.util.Scanner inputReader, String promptString, String validationRegEx, String... errorString) {
        String userInput = "";
        String errString = "Invalid input! Try again...";
        if (errorString.length > 0 && !errorString[0].trim().isEmpty()) {
            errString = errorString[0];
        }
        
        while (userInput.isEmpty()) {
            System.out.println();
            System.out.println(promptString);
            userInput = inputReader.nextLine();
            if (!userInput.matches(validationRegEx)) {
                System.err.println(errString);
                userInput = "";
            }
        }
        return userInput;
    }
    
}