Scanner nextLine() NoSuchElementException

3

我已经写了一段时间的Bukkit插件,但是有一个问题困扰了我。我试图使用Scanner从文件中读取一行,并将冒号之前的所有内容添加到HashSet中。每次尝试时,都会收到NoSuchElementException异常,看起来像这样:

21:01:01 [SEVERE] Could not pass event PlayerLoginEvent to ServerProtect
org.bukkit.event.EventException
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
va:341)
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.jav
a:62)
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.j
ava:477)
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.j
ava:462)
        at net.minecraft.server.ServerConfigurationManagerAbstract.attemptLogin(
ServerConfigurationManagerAbstract.java:273)
        at net.minecraft.server.NetLoginHandler.d(NetLoginHandler.java:112)
        at net.minecraft.server.NetLoginHandler.c(NetLoginHandler.java:41)
        at net.minecraft.server.DedicatedServerConnectionThread.a(DedicatedServe
rConnectionThread.java:44)
        at net.minecraft.server.DedicatedServerConnection.b(SourceFile:29)
        at net.minecraft.server.MinecraftServer.q(MinecraftServer.java:578)
        at net.minecraft.server.DedicatedServer.q(DedicatedServer.java:213)
        at net.minecraft.server.MinecraftServer.p(MinecraftServer.java:474)
        at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:406)
        at net.minecraft.server.ThreadServerApplication.run(SourceFile:539)
Caused by: java.util.NoSuchElementException: No line found
        at java.util.Scanner.nextLine(Unknown Source)
        at com.gmail.thecotlsdragon98.ServerProtect.AltAccounts.CheckForUsedIP(A
ltAccounts.java:49)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
va:339)
        ... 13 more

这是我尝试执行上述操作的类。
package com.gmail.thecotlsdragon98.ServerProtect;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Scanner;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;

public class AltAccounts implements Listener
{
    ServerProtect plugin;
    public AltAccounts(ServerProtect instance){
        plugin = instance;
    }
    File usersFile;
    FileWriter outputFile;
    PrintWriter out;
    Scanner in;
    HashSet<String> players = new HashSet<String>();
    StringBuffer buffer = new StringBuffer();
    @EventHandler
    public void newUsersFile(PluginEnableEvent event) throws IOException{
        if(event.getPlugin() == plugin){
            usersFile = new File("plugins\\ServerProtect\\users.yml");
            if(!usersFile.exists()){
                usersFile.createNewFile();
            }
        }
    }
    @EventHandler
    public void CheckForUsedIP(PlayerLoginEvent event) throws IOException{
        outputFile = new FileWriter(usersFile, true);
        out = new PrintWriter(outputFile);
        in = new Scanner(new FileReader(usersFile));
        String[] nameandIP;
        String name;
        String IP;
        String line = in.nextLine();
        while(in.hasNextLine() && !in.nextLine().isEmpty()){
            players.add(line.split(": ")[0]);
            if(!players.contains(event.getPlayer().getName())){
                out.println(event.getPlayer().getName() + ": " + event.getAddress().getHostAddress());
                out.close();
            }
        }
        if(!in.hasNextLine() || in.nextLine().isEmpty()){
            if(!players.contains(event.getPlayer().getName())){
                out.println(event.getPlayer().getName() + ": " + event.getAddress().getHostAddress());
                out.close();
                players.clear();
            }
        }
        if(!plugin.getConfig().getBoolean("alts.kick-on-login")){
            while(in.hasNextLine()){
                nameandIP = in.nextLine().split(": ");
                name = nameandIP[0];
                IP = nameandIP[1];
                if(event.getAddress().getHostAddress().equals(IP) && !event.getPlayer().getName().equals(name)){
                    for(final Player player : plugin.getServer().getOnlinePlayers()){
                        if(player.hasPermission("serverprotect.alts.notify")){
                            player.sendMessage(ChatColor.RED + event.getPlayer().getName() + " has the same IP as " + name + " (" + event.getAddress().getHostAddress() + ")");
                        }
                    }
                }
            }
        }
        else if(plugin.getConfig().getBoolean("alts.kick-on-login")){
            while(in.hasNextLine()){
                nameandIP = in.nextLine().split(": ");
                name = nameandIP[0];
                IP = nameandIP[1];
                if(event.getAddress().getHostAddress().equalsIgnoreCase(IP)){
                    event.setKickMessage("The IP address you've logged in with is used. Alternate account?");
                    event.setResult(Result.KICK_OTHER);
                }
            }
        }
    }
    public void Disable(PluginDisableEvent event)throws IOException{
        if(event.getPlugin() == plugin){
            in.close();
        }
    }
}

有人告诉我我在两次调用in.nextLine(),当我询问如何解决时,他却无视了我。非常感谢您的帮助。


1
我看到一个无限循环...如果你有另一行,并且它不是空的,你将无法离开那个循环(因为你没有推进光标)。 - Makoto
2个回答

4

试试这个:

import java.io.*;
import java.lang.*;
import java.util.*;
public class test {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNextLine()) {
            String line = in.nextLine();
            String parse = line.substring(0, line.lastIndexOf(':'));
            System.out.println(parse);
        }
    }
}

虽然我没有使用这段精确的代码,但那个方法有效。谢谢! - Theway2cool1
1
@Theway2cool1 别忘了标记为正确答案(旁边那个小绿色的勾勾哦)。 - Cat
1
我很高兴它对你有用!@Eric 谢谢你的关照 :-) - alvonellos

0

in.nextLine() 这里你调用了两次,但只检查了一次 hasNextLine()

在第二次调用时,你可能已经有了可用的行。

players.add(in.nextLine().split(": ")[0]);

如何修复?

String tempLine = in.nextLine();

然后对这个字符串进行操作

我添加了String line = in.nextLine(); 然后在while循环中,我执行了players.add(line.split(": ")[0]; 现在它会重复添加相同的内容。换句话说,文件中有重复的条目。 - Theway2cool1
我的错,我应该把整个类放到原始帖子中。它应该将“:”之前的文本添加到HashSet中,然后检查玩家用户名是否在HashSet中,然后再将其添加到文件中。原始帖子已编辑,显示整个类。 - Theway2cool1
我找不到任何将结果添加到 HashSet 的代码片段。 - kosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接