无法从文件中读取用户名

Cannot read usernames from file

我正在尝试实现一个仅包含用户名密码和电子邮件的注册面板。我将所有用户名和密码放在一个文本文件中 "usernames.txt"。但是如果用户单击提交按钮并且用户名已经存在,我的问题将无法正常工作(它应该显示带有文本 "Username already exists!" 的 JOptionPane)。这是我的代码:

submitButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader("usernames.txt"));
            } catch (FileNotFoundException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }
            try {   
                String line = br.readLine();
                StringBuilder sb = new StringBuilder();
                Pattern usernameAndPasswordPattern = Pattern.compile("^(\S+) (\S+)$");
                while (line != null) {
                    sb.append(line); // 
                    sb.append(System.lineSeparator()); // 
                    line = br.readLine();
                }
                String everything = sb.toString();
                Matcher userNameAndPasswordMatcher = usernameAndPasswordPattern.matcher(everything);

                //if username exists!
                while (userNameAndPasswordMatcher.matches()) {
                    String username = userNameAndPasswordMatcher.group(1);
                    String password = userNameAndPasswordMatcher.group(2);

                    if (username.equals(usernameTextField.getText())) {
                        int result = JOptionPane.showConfirmDialog(null, "Username already exists!", "Registration incomplete", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
                    }
                }

            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } finally {
                try {
                    br.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }                       
        }
    });

在这里你可以看到我面板上的图片

您说文件中的行由用户名和密码组成。然而你正在测试这样的匹配:

boolean matches = Pattern.matches(""+usernameTextField.getText(), line);  

以上问题。

  1. match 动词 PatternMatcher 表示 "it matches the entire string"。

  2. Pattern.matches(String, String) 的第一个参数应该是表示为字符串的正则表达式,而不仅仅是任何旧字符串。现在,如果您的用户名字母表受到适当限制,可能 可以使用该名称作为正则表达式。但这是个坏主意。

  3. 即使将 "match" 更改为 "find",您仍然可能让提供的用户名与密码或 部分 文件中的用户名。

断章取义(即忽略第 3 点),这样匹配会更好:

boolean matches = line.contains(""+usernameTextField.getText());  

或者也许

boolean matches = Pattern.find(
    Pattern.quote(""+usernameTextField.getText()), line);  

但是,这仍然存在您可能会得到错误匹配的问题;例如匹配部分用户名...甚至密码。

因此,正确的解决方案是制作一个匹配文件中 整个 用户名字段的正则表达式,或者将这些行拆分为多个字段(例如 String.split然后使用 String.equals 根据提供的用户名测试适当的字段。

虽然@StephenC 的回答适用于你的情况,但它非常具体,我认为可以更优雅地解决它。

既然你说了

,你定义一个将用户名和密码分成两组的 RegEx-Pattern 怎么样?

the usernames.txt are in the format {Username} {Password}

您可以使用 RegEx ^(\S+) (\S+)$,这意味着第 1 组中的一组非空字符 space,后跟一个 space,然后是一个非空字符一组非白色space字符(在https://regex101.com/查看)

这里是用Java自带的库实现的

private static final Pattern usernameAndPasswordPattern = Pattern.compile("^(\S+) (\S+)$");

public static void checkInput(String input) throws IOException {
  try(BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("usernames.txt"))))) {
    String line = br.readLine();
    while(line != null) {
      Matcher userNameAndPasswordMatcher = usernameAndPasswordPattern.matcher(line);

      if(userNameAndPasswordMatcher.matches()) {
        String username = userNameAndPasswordMatcher.group(1);
        String password = userNameAndPasswordMatcher.group(2);

        if(username.equals(input)) {
          System.out.println("Username exists!");
          System.out.println("Password is: " + password);
          break;
        }
      }
      line = br.readLine();
    }
  }
}

我用这个来测试它

public static void main(String[] args) throws IOException {
  System.out.println("main > calling checkInput('Gary')..");
  checkInput("Gary");
  System.out.println("main > calling checkInput('Donald')..");
  checkInput("Donald");
  System.out.println("main > calling checkInput('Gordon')..");
  checkInput("Gordon");
}

这是我的测试数据

Peter 123peter567
Gary newman
Gordon fr33m4n

和我的输出

main > calling checkInput('Gary')..
Username exists!
Password is: newman
main > calling checkInput('Donald')..
main > calling checkInput('Gordon')..
Username exists!
Password is: fr33m4n