关于java:Scanner在使用next()或nextFoo()之后跳过nextLine()?

Scanner is skipping nextLine() after using next() or nextFoo()?

我使用Scanner方法nextInt()nextLine()来读取输入。

它看起来像这样:

1
2
3
4
5
6
7
System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string");
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)

问题是在输入数值后,跳过第一个input.nextLine()并执行第二个input.nextLine(),这样我的输出如下所示:

1
2
3
4
Enter numerical value
3   // This is my input
Enter 1st string    // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string    // ...and this line is executed and waits for my input

我测试了我的应用程序,看起来问题在于使用input.nextInt()。 如果我删除它,那么string1 = input.nextLine()string2 = input.nextLine()都会按照我希望的那样执行。


这是因为Scanner.nextInt方法不会通过点击"Enter"来读取输入中创建的换行符,因此在读取该换行符后会返回对Scanner.nextLine的调用。

Scanner.next()或任何Scanner.nextFoo方法之后使用Scanner.nextLine(nextLine本身除外)时,您将遇到类似的行为。

解决方法:

  • 在每个Scanner.nextIntScanner.nextFoo之后调用Scanner.nextLine来消耗该行的其余部分,包括换行符

    1
    2
    3
    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
  • 或者,更好的是,通过Scanner.nextLine读取输入并将输入转换为您需要的正确格式。例如,您可以使用Integer.parseInt(String)方法转换为整数。

    1
    2
    3
    4
    5
    6
    7
    int option = 0;
    try {
        option = Integer.parseInt(input.nextLine());
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
    String str1 = input.nextLine();


问题在于input.nextInt()方法 - 它只读取int值。因此,当您继续使用input.nextLine()读取时,您会收到" n"Enter键。所以要跳过这个,你必须添加input.nextLine()。希望现在应该清楚这一点。

试试这样:

1
2
3
4
5
6
7
8
System.out.print("Insert a number:");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the
 character)
System.out.print("Text1:");
String text1 = input.nextLine();
System.out.print("Text2:");
String text2 = input.nextLine();


这是因为当你输入一个数字然后按Enter时,input.nextInt()只消耗数字,而不是"行尾"。当input.nextLine()执行时,它会消耗第一个输入中仍在缓冲区中的"行尾"。

而是在input.nextInt()之后立即使用input.nextLine()


java.util.Scanner似乎有很多关于这个问题的问题。我认为更可读/惯用的解决方案是在调用nextInt()后调用scanner.skip("[

]+")删除任何换行符。

编辑:正如下面提到的@PatrickParker,如果用户在数字后输入任何空格,这将导致无限循环。有关与skip一起使用的更好模式,请参阅他们的答案:https://stackoverflow.com/a/42471816/143585


这样做是因为input.nextInt();不捕获换行符。你可以通过在下面添加input.nextLine();来像其他人那样做。
或者,您可以使用C#样式并将nextLine解析为整数,如下所示:

1
int number = Integer.parseInt(input.nextLine());

这样做也很有效,它为您节省了一行代码。


你需要知道的事情:

  • 表示几行的文本也包含行之间的不可打印字符(我们称之为行分隔符)

    • 回车(CR - 用字符串文字表示为"
      "
      )
    • 换行(LF - 在字符串文字中表示为"
      "
      )
  • 当你从控制台读取数据时,它允许用户输入他的回复,当他完成时,他需要以某种方式确认这一事实。为此,用户需要按键盘上的"输入"/"返回"键。

    重要的是,除了确保将用户数据放置到标准输入(由Scanner表示,由Scanner读取)之外,此键还会在其后发送OS相关行分隔符(如Windows

    )。

    因此,当您向用户询问age之类的值,并且用户类型42并按Enter键时,标准输入将包含"42

    "。

问题

Scanner#nextInt(和其他Scanner#nextType方法)不允许Scanner使用这些行分隔符。它会从System.in中读取它们(扫描器怎么会知道用户没有更多的数字表示age值而不是面对空格?)这将从标准输入中删除它们,但它也会缓存那些行分隔符内部。我们需要记住的是,所有Scanner方法始终都是从缓存文本开始扫描的。

现在Scanner#nextLine()只是收集并返回所有字符,直到找到行分隔符(或流的结尾)。但是,由于在扫描程序的缓存中立即找到从控制台读取数字后的行分隔符,它会返回空字符串,这意味着扫描程序无法在这些行分隔符(或流结束)之前找到任何字符。
BTW nextLine也消耗那些行分隔符。

因此,当您想要求数字然后是整行时,同时避免因nextLine而导致的空字符串

  • 使用扫描程序缓存中的nextInt消耗行分隔符

    • 调用nextLine
    • 或者通过调用skip("\
      ")
      让扫描程序跳过与
      匹配的部分,代表行分隔符(有关
      的更多信息:https://stackoverflow.com/a/31060125)
  • 不要使用nextInt(也不是next或任何nextTYPE方法)。而是使用nextLine逐行读取整个数据,并将每行中的数字(假设一行只包含一个数字)解析为正确的类型,如int via Integer.parseInt

BTW:Scanner#nextType方法可以跳过分隔符(默认情况下所有空格,如制表符,行分隔符),包括扫描程序缓存的那些空格,直到它们找到下一个非分隔符值(标记)。感谢像"42

321

foobar"代码那样的输入

1
2
3
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();

将能够正确分配num1=42 num2=321 name=foobar


而不是input.nextLine()使用input.next(),这应该解决问题。

修改后的代码

1
2
3
4
5
6
7
8
9
10
11
public static Scanner input = new Scanner(System.in);

public static void main(String[] args)
{
    System.out.print("Insert a number:");
    int number = input.nextInt();
    System.out.print("Text1:");
    String text1 = input.next();
    System.out.print("Text2:");
    String text2 = input.next();
}


如果要快速扫描输入而不混淆Scanner类的nextLine()方法,请使用自定义输入扫描程序。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
class ScanReader {
/**
* @author Nikunj Khokhar
*/

    private byte[] buf = new byte[4 * 1024];
    private int index;
    private BufferedInputStream in;
    private int total;

    public ScanReader(InputStream inputStream) {
        in = new BufferedInputStream(inputStream);
    }

    private int scan() throws IOException {
        if (index >= total) {
            index = 0;
            total = in.read(buf);
            if (total <= 0) return -1;
        }
        return buf[index++];
    }
    public char scanChar(){
        int c=scan();
        while (isWhiteSpace(c))c=scan();
        return (char)c;
    }


    public int scanInt() throws IOException {
        int integer = 0;
        int n = scan();
        while (isWhiteSpace(n)) n = scan();
        int neg = 1;
        if (n == '-') {
            neg = -1;
            n = scan();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = scan();
            }
        }
        return neg * integer;
    }

    public String scanString() throws IOException {
        int c = scan();
        while (isWhiteSpace(c)) c = scan();
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = scan();
        } while (!isWhiteSpace(c));
        return res.toString();
    }

    private boolean isWhiteSpace(int n) {
        if (n == ' ' || n == '
'
|| n == '
'
|| n == '\t' || n == -1) return true;
        else return false;
    }

    public long scanLong() throws IOException {
        long integer = 0;
        int n = scan();
        while (isWhiteSpace(n)) n = scan();
        int neg = 1;
        if (n == '-') {
            neg = -1;
            n = scan();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = scan();
            }
        }
        return neg * integer;
    }

    public void scanLong(long[] A) throws IOException {
        for (int i = 0; i < A.length; i++) A[i] = scanLong();
    }

    public void scanInt(int[] A) throws IOException {
        for (int i = 0; i < A.length; i++) A[i] = scanInt();
    }

    public double scanDouble() throws IOException {
        int c = scan();
        while (isWhiteSpace(c)) c = scan();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = scan();
        }
        double res = 0;
        while (!isWhiteSpace(c) && c != '.') {
            if (c == 'e' || c == 'E') {
                return res * Math.pow(10, scanInt());
            }
            res *= 10;
            res += c - '0';
            c = scan();
        }
        if (c == '.') {
            c = scan();
            double m = 1;
            while (!isWhiteSpace(c)) {
                if (c == 'e' || c == 'E') {
                    return res * Math.pow(10, scanInt());
                }
                m /= 10;
                res += (c - '0') * m;
                c = scan();
            }
        }
        return res * sgn;
    }

}

好处 :

  • 扫描输入比BufferReader更快
  • 减少时间复杂性
  • 为每个下一个输入刷新缓冲区

方法 :

  • scanChar() - 扫描单个字符
  • scanInt() - 扫描整数值
  • scanLong() - 扫描长值
  • scanString() - 扫描字符串值
  • scanDouble() - 扫描双值
  • scanInt(int [] array) - 扫描完成数组(整数)
  • scanLong(long [] array) - 扫描完成数组(长)

用法:

  • 将给定代码复制到您的Java代码下面。
  • 给定类的初始化对象
  • ScanReader sc = new ScanReader(System.in);

    3.导入必要的类:

    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.InputStream;

    4.从main方法抛出IOException以处理Exception
    5.使用提供的方法。
    6.享受

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    class Main{
        public static void main(String... as) throws IOException{
            ScanReader sc = new ScanReader(System.in);
            int a=sc.scanInt();
            System.out.println(a);
        }
    }
    class ScanReader....

    为避免此问题,请在nextInt();之后立即使用nextLine();,因为它有助于清除缓冲区。当您按ENTER时,nextInt();不会捕获新行,因此稍后会跳过Scanner代码。

    1
    2
    3
    Scanner scanner =  new Scanner(System.in);
    int option = scanner.nextInt();
    scanner.nextLine(); //clearing the buffer

    如果要读取字符串和整数,则解决方案是使用两个扫描程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Scanner stringScanner = new Scanner(System.in);
    Scanner intScanner = new Scanner(System.in);

    intScanner.nextInt();
    String s = stringScanner.nextLine(); // unaffected by previous nextInt()
    System.out.println(s);

    intScanner.close();
    stringScanner.close();


    与解析输入相比,sc.nextLine()更好。
    因为表现明智,所以会很好。


    我想我参加派对的时间已经很晚了..

    如前所述,在获取int值后调用input.nextLine()将解决您的问题。您的代码无法正常工作的原因是因为没有其他内容可以从您的输入(您输入int的地方)存储到string1中。我只是对整个主题稍微透露一点。

    将nextLine()视为Scanner类中nextFoo()方法中的奇数。让我们举一个简单的例子..假设我们有两行代码,如下所示:

    1
    2
    int firstNumber = input.nextInt();
    int secondNumber = input.nextInt();

    如果我们输入下面的值(作为单行输入)

    54 234

    我们的firstNumbersecondNumber变量的值分别变为54和234。这样工作的原因是因为当nextInt()方法接受值时,不会自动生成新的换行符(即 n)。它只需要"下一个int"并继续前进。除了nextLine()之外,其他nextFoo()方法也是如此。

    nextLine()在获取值后立即生成新换行符;这就是@RohitJain所说的新线路被"消耗"的意思。

    最后,next()方法只是获取最近的String而不生成新行;这使得这成为在同一行中获取单独字符串的优先方法。

    我希望这有帮助..快乐编码!


    使用2个扫描仪对象而不是一个

    1
    2
    3
    4
    5
    Scanner input = new Scanner(System.in);
    System.out.println("Enter numerical value");    
    int option;
    Scanner input2 = new Scanner(System.in);
    option = input2.nextInt();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            int i = scan.nextInt();
            scan.nextLine();
            double d = scan.nextDouble();
            scan.nextLine();
            String s = scan.nextLine();

            System.out.println("String:" + s);
            System.out.println("Double:" + d);
            System.out.println("Int:" + i);
        }


    为什么不在每次阅读时使用新的扫描仪?如下。使用这种方法,您将无法面对您的问题。

    1
    int i = new Scanner(System.in).nextInt();