有没有办法使用扫描仪读取包括空格在内的完整字符串,而无需读取整行?

Is there a way to use scanner to read in a full string including the spaces, without reading the full line?

提问人:KidsSeeKanye 提问时间:11/14/2022 最后编辑:Hovercraft Full Of EelsKidsSeeKanye 更新时间:11/14/2022 访问量:65

问:

假设我的文本文件如下所示:

John Doe    18    male
Amy hun     19    female

我需要像这样将其读入数组

while(reader.hasNextLine()){

    result[i] = new Person(reader.next(),reader.next(),reader.next());
    reader.nextLine();
    i++;
}

但它一直搞砸我的数组,因为它将每个空格视为分隔符并且不使用它,其中列由空格分隔。

我尝试在扫描仪上使用分隔符来空格,但出现错误:线程“main”java.util.NoSuchElementException 中的异常。尝试了一些东西,但也没有运气。我也不能只将两个名称作为单独的字符串读取,因为有些行只有一个名称。

Java 数组 java.util.scanner 分隔符

评论

0赞 Hovercraft Full Of Eels 11/14/2022
你需要解析这一行,正则表达式可以帮助你做到这一点。
0赞 Hovercraft Full Of Eels 11/14/2022
例如: 所以行可以保持,然后代币在哪里持有:String line = reader.nextLine();"John Doe 18 male"String[] tokens = lineOfText.split("(?<=\\d)\\s+|\\s+(?=\\d)");{"John Doe", "18", "male"}
0赞 Hovercraft Full Of Eels 11/14/2022
其中,正则表达式在数字后跟空格:处拆分,或空格后跟数字:"(?<=\\d)\\s+|\\s+(?=\\d)""(?<=\\d)\\s+\\s+(?=\\d)"
0赞 KidsSeeKanye 11/14/2022
是的,谢谢。这为我指明了正确的方向。我用了: String[] array = words.split(“\\t”);

答:

0赞 Hovercraft Full Of Eels 11/14/2022 #1

您需要阅读每一行文本,然后使用正则表达式或“正则表达式”解析该行。正则表达式是一种灵活的方法,用于抓取与某些规则匹配的字符串部分。例如,如果逐行遍历文件,则使用以下命令抓取每一行:reader.nextLine()

while (reader.hasNextLine()) {
    String line = reader.nextLine();
    // ...
}

现在保存文件中的一行,例如line"John Doe 18 male"

然后,您需要将这一行拆分为 3 个子字符串,分别代表姓名、年龄和性别,它们由文本后跟数字后跟文本表示,所有子字符串均由空格(空格)分隔

如果调用 String,则可以使用正则表达式,该正则表达式将根据以下规则划分 String:.split(...)

String regex = "(?<=\\d)\\s+|\\s+(?=\\d)";

这之所以有效,是因为正则表达式在数字后跟空格:或空格后跟数字处拆分:使用正则表达式前瞻和后视规则。"(?<=\\d)\\s+|\\s+(?=\\d)"(?<=\\d)\\s+\\s+(?=\\d)

这会将字符串拆分为标记:{"John Doe", "18", "male"}

整个事情可能看起来像:

List<Person> personList = new ArrayList<>();

String regex = "(?<=\\d)\\s+|\\s+(?=\\d)";

while (reader.hasNextLine()) {
    String line = reader.nextLine();
    String[] tokens = line.split(regex);
    Person person = new Person(tokens[0], tokens[1], tokens[2]);
    // or perhaps:
    // Person person = new Person(tokens[0], Integer.parseInt(tokens[1]), tokens[2]);
    personList.add(person);
}
0赞 Bohemian 11/14/2022 #2

适当设置扫描仪的分隔符:

reader.useDelimiter("(?<=\\d)\\s+|\\s+(?=\\d)|\n");

观看现场演示

这会将分隔符设置为:

  • “数字后面的一些空格”,或者
  • “数字前的一些空格”,或
  • “换行符”

有了这个,你可以按原样使用你的代码(请参阅下面的测试代码)。


一些测试代码:

public static void main(String[] args) {
    String input ="John Doe    18    male\nAmy hun     19    female\n";
    Scanner reader = new Scanner(input).useDelimiter("(?<=\\d)\\s+|\\s+(?=\\d)|\n");
    Person[] result = new Person[10];
    int i = 0;
    while (reader.hasNext()) {
        result[i++] = new Person(reader.next(), reader.next(), reader.next());
    }
    Arrays.stream(result).filter(Objects::nonNull).forEach(System.out::println);
}

static class Person {
    private final String name;
    private final String age;
    private final String gender;

    Person(String name, String age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

输出:

Person{name='John Doe', age='18', gender='male'}
Person{name='Amy hun', age='19', gender='female'}