提问人:Connor_G 提问时间:11/28/2022 最后编辑:Jim GarrisonConnor_G 更新时间:11/28/2022 访问量:134
有没有办法在Java中“重置”扫描仪?
Is there way a "reset" a scanner in Java?
问:
重置在这里可能不是正确的词,但我目前正在构建一个程序,让用户查找名称,并通过扫描包含名称列表后跟数字的 txt 文件,程序然后显示该名称后面的数字。我这样做的方式是通过 .nextLine,但是如果用户输入列表中稍后的名称(例如示例中的 Samantha),然后尝试在列表顶部查找名称(如 Sally),则找不到第二个名称。
作为参考,下面是该 txt 文件的示例:
Sally 0 0 0 0 0 0 0 0 0 0 886
Sam 58 69 99 131 168 236 278 380 467 408 466
Samantha 0 0 0 0 0 0 272 107 26 5 7
Samir 0 0 0 0 0 0 0 0 920 0 798
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
public class BabyNames {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Scanner input = new Scanner (new File("BabyNames.txt"));
Scanner keyboard = new Scanner (System.in);
System.out.println("This program allows you to search through the data from the "
+ "Social Security Administration to see how popular a particular name has "
+ "been since 1900.");
System.out.print("Name? ");
String name = keyboard.nextLine();
do {
while(input.hasNextLine()) {
String text = input.nextLine();
String[] words = text.split(" ");
if (text.contains(name)) {
System.out.println("Statistics on name \"" + name + "\"");
for (int i = 1; i < words.length; i++) {
System.out.println((1900 + (i-1)*10) + ": " + words[i]);
}
System.out.println("Enter another name or type quit to exit.");
name = keyboard.nextLine();
break;
}
else if (name.contains("quit") || name.contains("quit")){
System.exit(0);
}
else {
continue;
}
System.out.print("Error, name not found.");
}
} while (!name.contains("quit") || name.contains("quit"));
}
}
我查找了 .reset 方法,但似乎不起作用。老实说,我在这里被难住了。
答:
通常,Java Scanner 不知道/控制文件中的指针位置。它包装在 InputStream 上,而 InputStream 又在每个 nextLine() 调用时向 Scanner 提供输入。
Scanner systemInput = new Scanner(System.in);
//new Scanner(new FileInputStream("file.t"));
InputStream 具有标记/重置功能,可以帮助我们控制指针位置。
(注意:标记/重置使我们能够标记检查点,您可以稍后跳回检查点。
不幸的是,FileInputStream 不支持它。但是,BufferedInputStream 派上用场了。
让我们为您的问题制定解决方案,
- 使用输入文件创建 FileInputStream。
- 用 BufferedInputStream 包装它,后者提供 mark() 和 reset() 函数。
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream("BabyNames.txt"));
- 将其作为输入提供给 Scanner 构造函数。
Scanner input = new Scanner (inputStream);
- 在文件开头标记检查点。
inputStream.mark(0);//saving a checkpoint
- 在内部 while 循环结束后,将指针重置到标记的位置。
inputStream.reset();
现在,您的代码工作正常。
评论
mark
BufferedInputStream
同样,不要尝试“重置”扫描仪或重新读取文件。最好的办法是读取文件一次,然后将所有数据放入某种类型的集合中,这里效果最好。我首先创建一个类来保存一行信息,可能称为 BabyName,它包含名称的 String 字段和名称后面列出的数字的整数列表,如下所示:Map<String, SomeCustomClass>
import java.util.*;
public class BabyName {
String name;
List<Integer> numberList = new ArrayList<>();
public BabyName(String name, List<Integer> numberList) {
this.name = name;
this.numberList = numberList;
}
public String getName() {
return name;
}
public List<Integer> getNumberList() {
return numberList;
}
@Override
public String toString() {
return "BabyName [name=" + name + ", numberList=" + numberList + "]";
}
// consider adding hashCode and equals methods that are based on the name field alone
// ...
}
然后,我建议在代码中使用一种方法,该方法采用从文件中提取的一行文本,并将其转换为 BabyName 对象:
private static BabyName createBabyName(String line) {
String[] tokens = line.split("\\s+");
String name = "";
List<Integer> numberList = new ArrayList<>();
// ... code to extract the data and that fills the numberList here
// ... left blank for you to fill in
BabyName babyName = new BabyName(name, numberList);
return babyName;
}
然后创建一个使用 name 字段作为映射键来保存 BabyName 对象,当您读取文件时(请注意一次),您填充映射:Map<String, BabyName> babyNameMap = new HashMap<>();
Scanner fileScanner = null;
try {
fileScanner = new Scanner(new File(FILE_PATH_NAME));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(-1);
}
// read file and fill the map
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
BabyName babyName = createBabyName(line);
babyNameMap.put(babyName.getName(), babyName);
}
然后,您可以使用此映射多次从用户那里获取数据,而无需重新读取文件或重复使用扫描仪。
例如,
String nameEnteredByUser = keyboard.nextLine();
BabyName selectedBabyName = babyNameMap.get(nameEnteredByUser);
// check for null here first
String name = nameEnteredByUser;
List<Integer> numberList = selectedBabyName.getNumberList();
评论
HashMap<String, String>