Java 如何检查扫描仪是否已关闭
我一直在尝试写的两种方法都有问题。两者都涉及使用扫描仪读取文件,其中每一行都以逗号分隔。这些方法是我的FileIO类的一部分。除了那门课,我还有另外两门课,食物和食物清单。食物对象包含来自食物捐赠的多条信息(捐赠物品的人、捐赠原因等)。FoodArrayList类的功能与ArrayList几乎相同,只是我创建它只是为了存储食物对象 我正在努力解决的两种方法如下:Java 如何检查扫描仪是否已关闭,java,Java,我一直在尝试写的两种方法都有问题。两者都涉及使用扫描仪读取文件,其中每一行都以逗号分隔。这些方法是我的FileIO类的一部分。除了那门课,我还有另外两门课,食物和食物清单。食物对象包含来自食物捐赠的多条信息(捐赠物品的人、捐赠原因等)。FoodArrayList类的功能与ArrayList几乎相同,只是我创建它只是为了存储食物对象 我正在努力解决的两种方法如下: 读取文件,并简单地计算文件中的行数。它返回行数。此方法用于确定FoodArray列表的大小。这是因为文件的每一行都描述了一个食物对象
if
语句来检测扫描仪是否关闭。在这两种方法中,我在方法的开头有以下内容:
try{
if(scan.hasNext() == false || scan == null)
scan = new Scanner(new File(this.getFileName()));
}
catch(FileNotFoundException fnfe){
System.err.println("The " + fileName + " could not be found.");
}
catch(IOException ioe){
ioe.printStackTrace();
}
但这似乎不起作用。如果我先使用方法1,然后再尝试使用方法2(请记住,我在每个方法结束时关闭了扫描仪),则跳过If
语句,scan
将永远不会重新实例化,并向我抛出非法状态异常
我应该在前面提到的一个要点是:我希望这两种方法都是可重用的。如果方法#1一直持续到文件结束,而我稍后使用方法#2,我希望Scanner对象再次从文件开始读取。看起来唯一的方法就是重新实例化扫描器对象
当我第一次了解Java中的I/O时,我记得有人告诉我,在使用完扫描仪对象后,一定要关闭它们。这几乎是我脑子里根深蒂固的东西。不管怎样,我该如何应对呢?我的一个想法是在两种方法的末尾将scan
设置为null。这有必要吗?我在StackOverflow的其他文章中读到过,这会导致我甚至不关闭扫描仪对象,而让垃圾收集器来处理它
除此之外,我还想知道一旦扫描仪关闭,它到底会发生什么,为什么不能重新打开。我知道它与流有关,但我不知道在Java上下文中这些是什么。我试着查了一下,但没能从中得到多少理解
以下是我的两种方法的代码:
方法#1
public int numberOfLines(){
try{
if(scan.hasNext() == false || scan == null)
scan = new Scanner(new File(this.getFileName()));
}
catch(FileNotFoundException fnfe){
System.err.println("The " + fileName + " could not be found.");
}
catch(IOException ioe){
ioe.printStackTrace();
}
int lineCount = 0;
while(scan.hasNextLine()){
scan.nextLine();
lineCount++;
}
scan.close();
return lineCount;
}
方法#2
public void readFile(FoodArrayList fal){
try{
if(scan.hasNext() == false || scan == null)
scan = new Scanner(new File(this.getFileName()));
}
catch(FileNotFoundException fnfe){
System.err.println("The " + fileName + " could not be found.");
}
catch(IOException ioe){
ioe.printStackTrace();
}
while(scan.hasNextLine()){
String stringRead = scan.nextLine();
StringTokenizer tokens = new StringTokenizer(stringRead,",");
Food temp = new Food();
temp.setCorpName(tokens.nextToken());
temp.getContact().setLast(tokens.nextToken());
temp.getContact().setFirst(tokens.nextToken());
temp.setDate(tokens.nextToken());
temp.setProductCode(tokens.nextToken());
temp.setDescription(tokens.nextToken());
temp.setReason(tokens.nextToken());
String numberString = tokens.nextToken();
int number = Integer.parseInt(numberString);
temp.setNumber(number);
temp.setCoP(tokens.nextToken());
fal.insert((Food)temp);
}
scan.close();
}
我想把这两种方法分开。这是因为在我的客户机类中,我执行以下操作:
FoodArrayList list;
FileIO fio = new FileIO();
int listSize = fio.numberOfLines();
list = new FoodArrayList(listSize);
fio.readFile(list);
FileIO类的默认构造函数已经考虑了我试图读取的特定文件。当然,重载构造函数允许使用不同的文件名作为输入。在此方面的任何帮助都将不胜感激
我希望这两种方法都是可重用的。如果方法#1一直持续到文件结束,而我稍后使用方法#2,我希望Scanner对象再次从文件开始读取。看起来唯一的方法就是重新实例化扫描器对象
看来你已经找到答案了。您想重新实例化扫描仪
对象,而不管其中一个对象可能处于何种状态,所以只要…这样做
在方法开始时,声明并实例化扫描仪
引用。您还可以使用try with resources
,这样您的扫描仪在运行结束时总是关闭的
public void countLines() {
try(Scanner scan = new Scanner(new File("file.txt"))) {
// code
} catch (IOException e) {
e.printStackTrace();
}
}
即使在现实中,您正在做的工作可以用相同的方法完成,但如果您坚持分别执行这些操作,那么初始化两个不同的扫描仪是您的最佳选择。如果(scan.hasNext()==false | | scan==null)
您应该交换条件,因为如果有可能scan
对象为null
,那么您应该首先检查它。此外,只有在将食物
对象存储在数组中时,才需要第一种方法。但我猜您已经在使用一些集合,而不是必需的行计数。什么是FoodArray列表?当调用其构造函数并将listsize作为参数传递时,您到底想做什么?FoodArrayList是一个与ArrayList对象操作相同的类,只是它被设计为仅存储食物对象。我知道我可以使用ArrayList的一个实例,但我有创建这个特定类的理由。当我将listSize作为参数传递时,我基本上是在创建一个具有listSize大小的食物对象数组。我可以手动计算文件和代码中放入list=new foodaryList(24)
的行数。然而,从我对编码行业的理解来看,我们通常希望避免硬编码,并使代码具有灵活性。这就是我创建numberOfLines()
方法的原因。我遵循您所说的。但是,这两个方法是FileIO类的一部分。在我的构造函数中,我已经实例化了我的Scanner对象。也许我误解了你的观点。你是说即使使用if
语句也不要重新启动扫描仪?这样,无论我如何定义FileIO类的构造函数都无关紧要,因为我希望这些方法从