我在这里有一个非常奇怪的问题。抛出并处理我的ReaderException异常后,我的读入操作仍然在异常的第一次出现时停止。有人可以解释为什么会这样吗?
输入:
Hotel Paradis;Strada Ciocarliei, Cluj-Napoca 400124;46.779862;23.611739;7;200;8;250;1;400
Hotel Sunny Hill;Strada Fagetului 31A, Cluj-Napoca 400497;46.716030;23.573740;4;150;6;190
Golden Tulip Ana Dome;Strada Observatorului 129, Cluj-Napoca 400352;46.751989;23.576580;0;330;0;350;0;600
代码:
public HotelDescriptor readLine(final String line) throws ReaderException {
System.out.println(line);
String info[] = line.split(";");
for (String i:info)
System.out.println(i);
String tempname = info[0];
String tempaddress = info[1];
float templatitudeh = Float.parseFloat(info[2]);
float templongitudeh = Float.parseFloat(info[3]);
int singleroom = Integer.parseInt(info[4]);
int singleprice = Integer.parseInt(info[5]);
int doubleroom = Integer.parseInt(info[6]);
int doubleprice = Integer.parseInt(info[7]);
int suiteroom = Integer.parseInt(info[8]);
int suiteprice = Integer.parseInt(info[9]);
Hotel tempHotel = new Hotel(tempname, tempaddress, templatitudeh, templongitudeh, singleroom, singleprice, doubleroom, doubleprice, suiteroom, suiteprice);
System.out.println(tempHotel.getName());
return tempHotel;
}
public List<HotelDescriptor> readFile(final String hotels) {
try (BufferedReader buff = new BufferedReader(new FileReader(hotels))) {
String line = "";
while ((line = buff.readLine() )!= null) {try {
hotelData.add(readLine(line));
} catch (ReaderException e){
e.printStackTrace();
} catch (ArrayIndexOutOfBoundsException ex){
ex.printStackTrace();
}
//line = buff.readLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return hotelData;
}
答案 0 :(得分:0)
我认为 hotelData 被声明为Class字段(类全局)。
在阅读文本文件时,您应该考虑可能发生(或不发生)的一些异常。可以采取简单的步骤以确保读取该文本文件相对成功。如果您的应用程序正在创建文本文件,那么您的成功率会大大提高,因为您可以控制它的编写方式,但是,如果您的应用程序未创建文本文件或文本文件是从远程源编译的,那么成功率可以降低,除非采取措施确保预期的结果。
在我看来:
int suiteroom = Integer.parseInt(info[8]);
被命中时发生。没错,你得到了一个
ArrayIndexOutOfBoundsException ,因为 info [] 数组中根本没有索引 8 。您需要在代码中处理这样的情况并准备处理它们。不要依赖
处理业务的异常处理。整个想法
是否避免例外,如果有可能,请注意有时需要。我不相信这是其中之一。如果不访问您的代码类,我只会自然地假设您的方法返回有效且按计划运行。考虑到这一点,我将如何格式化酒店文本文件:
My App Name - Hotels Data File
;Hotel Name; Hotel Address; Latitude; Longtitude; Single Room; Single Price; Double Room; Double Price; Suite Room; Suite Price
Hotel Paradis;Strada Ciocarliei, Cluj-Napoca 400124;46.779862;23.611739;7;200;8;250;1;400
Hotel Sunny Hill;Strada Fagetului 31A, Cluj-Napoca 400497;46.716030;23.573740;4;150;6;190
Golden Tulip Ana Dome;Strada Observatorului 129, Cluj-Napoca 400352;46.751989;23.576580;0;330;0;350;0;600
该文件的第一行是文件描述符行。第二行是空白行,只是为了更方便地查看文件。第三行被视为注释行,因为在这种情况下,它以分号(; )开头。实际上由您来决定将文件行视为注释行的原因。此行仅用作标题行,并描述了数据行上每个分隔数据的含义。第四行当然是另一个空白行,并且再次,以便于查看文件。其余文件行都是数据行,这些是您要处理的文件行。
要读取文件,您的方法可能如下所示:
public HotelDescriptor readLine(final String line) {
// Split on various possible combinations of how the
// delimiter might be formated within a file line.
String info[] = line.split(" ; |; |;");
// Variables declaration and default initialization values
String tempname = "";
String tempaddress = "";
float templatitudeh = 0.0f;
float templongitudeh = 0.0f;
int singleroom = 0;
int singleprice = 0;
int doubleroom = 0;
int doubleprice = 0;
int suiteroom = 0;
int suiteprice = 0;
String strg; // Used to hold the current Array Element in the for/loop
String regExF = "-?\\d+(\\.\\d+)?"; // RegEx to validate a string float or double value.
String regExI = "\\d+"; // RegEx to validate a string Integer value.
for (int i = 0; i < info.length; i++) {
strg = info[i].trim(); // remove leading/trailing spaces if any
switch (i) {
case 0:
tempname = info[i];
break;
case 1:
tempaddress = info[i];
break;
case 2:
// Is it a float or double numerical value
if (strg.matches(regExF)) {
templatitudeh = Float.parseFloat(info[i]);
}
break;
case 3:
// Is it a float or double numerical value
if (strg.matches(regExF)) {
templongitudeh = Float.parseFloat(info[i]);
}
break;
case 4:
// Is it a Integer numerical value
if (strg.matches(regExI)) {
singleroom = Integer.parseInt(info[i]);
}
break;
case 5:
// Is it a Integer numerical value
if (strg.matches(regExI)) {
singleprice = Integer.parseInt(info[i]);
}
break;
case 6:
// Is it a Integer numerical value
if (strg.matches(regExI)) {
doubleroom = Integer.parseInt(info[i]);
}
break;
case 7:
// Is it a Integer numerical value
if (strg.matches(regExI)) {
doubleprice = Integer.parseInt(info[i]);
}
break;
case 8:
// Is it a Integer numerical value
if (strg.matches(regExI)) {
suiteroom = Integer.parseInt(info[i]);
}
break;
case 9:
// Is it a Integer numerical value
if (strg.matches(regExI)) {
suiteprice = Integer.parseInt(info[i]);
}
break;
}
}
Hotel tempHotel = new Hotel(tempname, tempaddress, templatitudeh, templongitudeh,
singleroom, singleprice, doubleroom, doubleprice, suiteroom, suiteprice);
System.out.println(tempHotel.getName());
return tempHotel;
}
public List<HotelDescriptor> readFile(final String hotels) {
try (BufferedReader buff = new BufferedReader(new FileReader(hotels))) {
String line;
int lineCounter = 0;
while ((line = buff.readLine()) != null) {
// Trim any leading or trailing spaces (spaces, tabs, etc)
line = line.trim();
lineCounter++;
// Is this the right file to read?
if (lineCounter == 1) {
if (!line.equalsIgnoreCase("My App Name - Hotels Data File")) {
//No it isn't...
JOptionPane.showMessageDialog(this, "Invalid Hotels Data File!",
"Invalid Data File", JOptionPane.WARNING_MESSAGE);
break; // Get out of while loop
}
// Otherwise skip the File Descriptor line.
else { continue; }
}
// Is this a blank or Comment line...
// Lines that start with ; are comment lines
if (line.equals("") || line.startsWith(";")) {
// Yes it is...skip this line.
continue;
}
// Process the data line...
hotelData.add(readLine(line));
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return hotelData;
}
在 readLine()方法中,变量初始化为保持默认值,不应该在任何给定文件数据行上都存在所有值。 开关块可确保只处理提供的数据行值,而不管数据的提供方式如何,默认值将填写其余数据。这消除了在使用 info [] 数组时发生 ArrayIndexOutOfBoundsException 的可能性。
使用 parseFloat()和 parseInt()时,首先检查要转换为其各自数据类型的字符串,以确保它是有效的数字表示形式我们要转换的数据类型。 String.matches()方法与正则表达式结合使用。
上面的代码当然可以进一步优化,但我觉得它提供了一个很好的描述,可以做些什么来提高阅读和处理文件的成功率。
作为旁注,通过与BufferedReader使用的方法相同的名称调用您自己的方法( readLine())也是令人困惑的。由您决定,但这可能更好地命名为 processReadLine()
价格至少应为浮点数或双数据类型