我正在尝试编写两个方法,但遇到了一些问题。这两个方法都涉及使用Scanner读取文件,其中每一行都是逗号分隔的。这些方法是我FileIO类的一部分。除了该类之外,我还有另外两个类,Food和FoodArrayList。Food对象包含来自食品捐赠的多个信息(捐赠物品的人,捐赠原因等)。FoodArrayList类与ArrayList的功能基本相同,只不过我仅为存储Food对象而创建它。
我正在努力解决的两个方法如下:
1. 读取文件并简单地计算文件中行数。它返回行数。此方法用于确定FoodArrayList的大小。这是因为文件的每一行描述了一个Food对象。
2. 读取文件并将信息存储到FoodArrayList对象中。请记住,每个逗号分隔的行描述一个Food对象。因此,此方法通过文件,创建Food对象,并将它们插入到FoodArrayList中,直到到达文件末尾。
我所遇到的问题是在两个方法中都关闭了我的Scanner。我一直在思考如何编写一个if语句来检测Scanner是否已关闭。在这两个方法中,我在方法的开头都有以下内容:
这种方法似乎不起作用。如果我首先使用方法#1,然后稍后尝试使用方法#2(记住,在每个方法的末尾关闭Scanner),则if语句将被跳过,scan将永远不会被重新实例化,并将抛出IllegalStateException。
一个非常重要的观点是:我希望两种方法都可重复使用。如果方法#1一直运行到文件结束,然后我稍后使用方法#2,我希望Scanner对象再次从文件开头读取。而唯一的方法似乎是重新实例化Scanner对象。
当我第一次学习Java中的I/O时,我记得被告知始终确保在使用完它们后关闭Scanner对象。那几乎已经深入我的大脑了。无论如何,我该怎么办呢?我想到的一个想法是在我的两个方法的末尾将scan设置为null。那是否必要呢?我在StackOverflow的其他帖子上读到,这会让我不关闭Scanner对象,只需让垃圾收集器处理即可。
除此之外,我还想知道Scanner关闭后会发生什么以及为什么它无法重新打开。我知道这与流有关,但在Java环境下我不确定流是什么。我尝试查找Stream类, 但并没有从中获得太多的理解。
以下是两种方法的代码:
我的FileIO类的默认构造函数已经考虑了我要读取的特定文件。当然,重载的构造函数允许使用不同的文件名作为输入。如有需要,请提供帮助。
我正在努力解决的两个方法如下:
1. 读取文件并简单地计算文件中行数。它返回行数。此方法用于确定FoodArrayList的大小。这是因为文件的每一行描述了一个Food对象。
2. 读取文件并将信息存储到FoodArrayList对象中。请记住,每个逗号分隔的行描述一个Food对象。因此,此方法通过文件,创建Food对象,并将它们插入到FoodArrayList中,直到到达文件末尾。
我所遇到的问题是在两个方法中都关闭了我的Scanner。我一直在思考如何编写一个if语句来检测Scanner是否已关闭。在这两个方法中,我在方法的开头都有以下内容:
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(记住,在每个方法的末尾关闭Scanner),则if语句将被跳过,scan将永远不会被重新实例化,并将抛出IllegalStateException。
一个非常重要的观点是:我希望两种方法都可重复使用。如果方法#1一直运行到文件结束,然后我稍后使用方法#2,我希望Scanner对象再次从文件开头读取。而唯一的方法似乎是重新实例化Scanner对象。
当我第一次学习Java中的I/O时,我记得被告知始终确保在使用完它们后关闭Scanner对象。那几乎已经深入我的大脑了。无论如何,我该怎么办呢?我想到的一个想法是在我的两个方法的末尾将scan设置为null。那是否必要呢?我在StackOverflow的其他帖子上读到,这会让我不关闭Scanner对象,只需让垃圾收集器处理即可。
除此之外,我还想知道Scanner关闭后会发生什么以及为什么它无法重新打开。我知道这与流有关,但在Java环境下我不确定流是什么。我尝试查找Stream类, 但并没有从中获得太多的理解。
以下是两种方法的代码:
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类的默认构造函数已经考虑了我要读取的特定文件。当然,重载的构造函数允许使用不同的文件名作为输入。如有需要,请提供帮助。
scan
对象可能为空,则应首先检查它。此外,如果您正在将Food
对象存储在数组中,则只需要第一个方法。但我猜您已经在使用某些集合,不需要行数。 - YoungHobbitlist = new FoodArrayList(24)
。然而,根据我对编程专业的理解,我们通常希望避免硬编码并使我们的代码具有灵活性。这就是为什么我创建了numberOfLines()
方法的原因。 - coolDude