I'd have a pretty strange question here. After throwing and handling my ReaderException exception my read-in still stops at the first occurence of the exception. Can somebody please explain why is this happening?
Input:
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
Code:
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;
}
I take it that hotelData is declared as a Class field (class global).
When reading in a text file you should take into consideration some anomalies that can happen (or not). Simple steps can be taken to ensure that reading of that text file will be relatively successful. If your application is creating the text file then your success rate raises considerably since you can control how it is written but, if your application is not creating the text file or the text file is compiled from remote sources then the success rate can be reduced unless steps are taken to ensure expected results.
In my opinion:
int suiteroom = Integer.parseInt(info[8]);
is hit. That's right, you get a
ArrayIndexOutOfBoundsException because there simply is no index 8 within the info[] array. You need to handle situations like this in your code and prepare to deal with them. Don't rely on
exception handling to take care of business for you. The whole idea
is to avoid exceptions if at all possible mind you there are times when it is necessary. I don't believe this is one of them.Without access to your code classes I'm just going to naturally assume that your method returns are valid and functioning as planned. With this in mind, here is how I would format the Hotels text file:
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
The first line of the file is the File Descriptor line. The second line is a Blank Line simply for easier viewing of the file. The third line is considered a Comment Line because in this case it starts with a semi-colon (;). It's actually up to you to decide what is to be in place to make a file line considered as a Comment line. This line simply acts as a Header Line and describes what each delimited piece of data on any Data Line means. The fourth line is of course yet another blank line and again, for easier viewing of the file. The remaining file lines are all Data Lines and these are the file lines you want to process.
To read the file your methods might look like this:
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;
}
In the readLine() method variables are initialized to hold default values should not all values be present on any given file Data Line. The switch block ensures that only supplied data line values are processed regardless of how data is provided, defaults fill in the rest. This eliminates the possibility of an ArrayIndexOutOfBoundsException from happening when working with the info[] Array.
Where parseFloat() and parseInt() are used the string to be converted into its respective data type is first checked to ensure that it is a valid numerical representation of the data type we are converting to. The String.matches() method is used for this in conjunction with a regular expression.
The code above can of course be optimized much further but I feel it provides a good description of what can be done to to increase the success of reading and processing the file(s).
As a side note, it is also understandably confusing to call one of your own methods (readLine()) by the same name as a method used by BufferedReader. Up to you but perhaps this would be better named as processReadLine()
Prices should be at least in either float or double data type