Tôi đang gặp một số sự cố với hai phương pháp mà tôi đã cố gắng viết. Cả hai đều liên quan đến việc sử dụng một Máy quét để đọc trong một tệp, trong đó mỗi dòng được phân tách bằng dấu phẩy. Các phương thức này là một phần của lớp FileIO của tôi. Ngoài lớp học đó, tôi còn có hai lớp khác, Food và FoodArrayList. Các đối tượng thực phẩm có chứa một số thông tin từ các khoản quyên góp thực phẩm (những người quyên góp các mặt hàng, lý do quyên góp, vv). Lớp FoodArrayList khá nhiều có chức năng giống như một ArrayList, ngoại trừ việc tôi đã tạo ra nó chỉ với mục đích lưu trữ các đối tượng Thực phẩm.Cách kiểm tra xem máy quét có bị đóng
Hai phương pháp Tôi đang phải vật lộn với như sau:
- Đọc trong file và chỉ cần đếm số dòng trong file. Nó trả về số dòng. Phương pháp này được sử dụng để xác định kích thước của một FoodArrayList. Điều này là do mỗi dòng của tệp mô tả đối tượng Thực phẩm.
- Đọc trong tệp và lưu trữ thông tin vào đối tượng FoodArrayList. Hãy nhớ rằng mỗi dòng phân cách bằng dấu phẩy mô tả đối tượng Thực phẩm. Do đó, phương pháp này đi qua các tập tin, tạo ra các đối tượng thực phẩm, và chèn chúng vào một FoodArrayList cho đến khi nó đạt đến cuối của tập tin.
Điều tôi đang gặp phải là tôi đóng Máy quét của mình theo cả hai phương pháp. Và tôi đã đấu tranh với cách viết một câu lệnh if
để phát hiện xem Máy quét đã được đóng chưa. Trong cả hai phương pháp, tôi có những điều sau đây ngay từ đầu phương thức:
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();
}
Điều này dường như không hoạt động. Nếu tôi sử dụng phương pháp # 1 đầu tiên và sau đó thử sử dụng phương pháp # 2 (nhớ rằng tôi đóng Máy quét ở cuối mỗi phương pháp), câu lệnh if
bị bỏ qua và scan
không bao giờ được khôi phục và tôi bị ném IllegalStateException
.
Điểm rất lớn mà tôi nên đề cập trước đó là: Tôi muốn cả hai phương pháp có thể sử dụng lại được. Nếu phương thứC# 1 tiếp tục cho đến khi kết thúc tệp và sau đó tôi sử dụng phương pháp # 2, tôi muốn đối tượng Máy quét đọc từ đầu tệp một lần nữa. Và có vẻ như cách duy nhất để làm điều này là để phục hồi đối tượng Scanner.
Khi tôi lần đầu tiên biết về I/O trong Java, tôi nhớ mình đã nói đến luôn hãy chắc chắn để đóng đối tượng Scanner khi bạn đã hoàn tất việc sử dụng chúng. Đó là cái gì đó đã được ăn sâu vào não của tôi gần như. Bất kể, làm thế nào để tôi có được điều này? Một suy nghĩ tôi đã có là để thiết lập scan
để null ở phần cuối của cả hai phương pháp của tôi. Điều đó có cần thiết không? Tôi đã đọc trên các bài viết khác trong StackOverflow mà sẽ dẫn tôi đến thậm chí không đóng đối tượng Scanner của tôi và chỉ để cho các nhà sưu tập rác chăm sóc nó.
Ngoài tất cả điều này, tôi cũng tự hỏi chính xác những gì sẽ xảy ra với Máy quét khi nó được đóng và tại sao nó không thể mở lại được. Tôi hiểu rằng nó có liên quan đến các luồng, nhưng tôi không biết chính xác những gì trong ngữ cảnh của Java. Tôi đã cố gắng tìm kiếm các Stream class, nhưng đã không thể có được nhiều sự hiểu biết từ nó.
Đây là mã từ cả hai phương pháp của tôi:
Phương pháp # 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;
}
Phương pháp # 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();
}
Tôi muốn giữ hai phương pháp riêng biệt. Điều này là do trong lớp khách hàng của tôi, tôi thực hiện như sau:
FoodArrayList list;
FileIO fio = new FileIO();
int listSize = fio.numberOfLines();
list = new FoodArrayList(listSize);
fio.readFile(list);
Trình tạo mặc định của lớp FileIO của tôi đã xem xét tệp cụ thể mà tôi đang cố gắng đọc. Tất nhiên, hàm tạo quá tải cho phép một hàm sử dụng một tên tệp khác làm đầu vào. Bất kỳ trợ giúp về điều này sẽ được đánh giá cao.
'if (scan.hasNext() == false || scan == null)' bạn nên trao đổi các điều kiện, bởi vì nếu có khả năng 'đối tượng quét' là 'null' thì bạn nên kiểm tra nó trước. Ngoài ra, bạn chỉ cần phương thức đầu tiên nếu bạn đang lưu trữ các đối tượng 'Food' trong một mảng. Nhưng tôi đoán bạn đã sử dụng một số bộ sưu tập, không yêu cầu số lượng dòng. – YoungHobbit
danh sách FoodArrayList là gì? chính xác những gì bạn muốn làm khi bạn gọi constructor của nó và vượt qua listize như là một đối số? –
FoodArrayList là một lớp hoạt động giống như một đối tượng ArrayList, ngoại trừ việc nó được thiết kế để chỉ lưu trữ các đối tượng Thực phẩm. Tôi biết tôi có thể chỉ sử dụng một thể hiện của ArrayList, nhưng tôi có lý do của tôi để tạo ra lớp học đặc biệt này. Khi tôi chuyển listSize thành một đối số, về cơ bản tôi tạo một mảng các đối tượng Food với kích thước của listSize. – coolDude