Exception organization assistance? - java

I had some success with this site, and I hope I find more excellent programmers to assist me.
So I am at my wit's end with this code. I am very new to programming, especially exceptions. I have looked very hard through my course material and sought help, but I have been quite unsuccessful. I am trying to create an improved parser that will override another parser. It reads a .txt file with student information of it including an ID, a name, a grade, and an optional email address and optional comment as tokens in a String separated by commas. The override checks for errors in each token and throws an exception called ParserException. The exception will check the code and then return an error message if the error is unfixable.
For example, if a student puts in an AB for the grade, the exception will flag and check if the input is a valid grade (which it is) and then return, if it is not, then it will throw a ParserException, in this case
throw new ParserException(ParserException.GRADE_INVALID_GRADE,lineIndex);
This shows that the does not work and sends out a message GRADE_INVALID on the line indexLine
I have a list of what I need to have as an output:
Any violation of the file format specified in the Input File Format Description section above should result in an ParcerException with an appropriate message
Duplicate IDs are not allowed
Grade values must be a float (92.0) or a letter grade and not an integer
I have all the code to correct and check for errors, but I cannot figure out how to get the try-catch to work. Here's is the override code:
#Override
public ParserResult parseLine(int lineIndex) {
String[] tokens = lines.get(lineIndex).split(",");
ArrayList<Integer> idList = new ArrayList<Integer>();
Integer studentId;
String name;
String grade;
String email;
String comments;
boolean isFloat;
float gradeFinal;
String editName;
studentId = new Integer(tokens[0]);
ParserResult result;
try{
return super.parseLine(lineIndex);
}
catch(ParserException e){
// Check reasonable number of tokens
if(tokens.length >= 3 && tokens.length <= 5){
name = tokens[1];
grade = tokens[2];
// Check the student ID
if(idList.contains(studentId)){
throw new ParserException(ParserException.DUPLICATE_ID, lineIndex);
}else{
idList.add(studentId);
}
// Check the grade
if(grade.trim().equalsIgnoreCase("A")){
gradeFinal = gradeA;
}else if(grade.trim().equalsIgnoreCase("AB")){
gradeFinal = gradeAB;
}else if(grade.trim().equalsIgnoreCase("B")){
gradeFinal = gradeB;
}else if(grade.trim().equalsIgnoreCase("BC")){
gradeFinal = gradeBC;
}else if(grade.trim().equalsIgnoreCase("C")){
gradeFinal = gradeC;
}else if(grade.trim().equalsIgnoreCase("CD")){
gradeFinal = gradeCD;
}else if(grade.trim().equalsIgnoreCase("D")){
gradeFinal = gradeD;
}else if(grade.trim().equalsIgnoreCase("F")){
gradeFinal = gradeF;
}else{
try{
Integer.parseInt(grade);
isFloat = false;
}
catch(Exception fl) {
isFloat = true;
}
if(isFloat){
if((Float.parseFloat(grade) < 100f) && (Float.parseFloat(grade) >= 0f)){
gradeFinal = Float.parseFloat(grade);
}else{
throw new ParserException(ParserException.GRADE_INVALID_GRADE,lineIndex);
}
}else{
throw new ParserException(ParserException.GRADE_INTEGER_VALUE,lineIndex);
}
}
// Check the name
if(name.split(" ").length > 3){
throw new ParserException(ParserException.UNKNOWN, lineIndex);
}else{
editName = name.trim().split(" ")[0];
}
result = new ParserResult(studentId, editName, gradeFinal);
// Checks the email
if(tokens.length >= 4){
email = tokens[3];
// Check for at sign
if(!email.contains("#")){
throw new ParserException(ParserException.UNKNOWN, lineIndex);
}
int count = 0;
// Counts number of # symbols
for(int i=0; i<email.length(); i++){
if(email.indexOf(i) == '#'){
count++;
}
}
if(count > 1){
throw new ParserException(ParserException.EMAIL_MULTIPLE_AT,lineIndex);
}
if(email.split(".").length == 2){
if(!(email.trim().split(".")[1].contains(".edu")) && !(email.trim().split(".")[1].contains(".com"))){
throw new ParserException(ParserException.EMAIL_NOT_EDU_OR_COM,lineIndex);
}else{
result.setEmail(email);
}
}
// Checks if email contains .com or .edu
// Checks the comments
if(tokens.length == 5){
comments = tokens[4];
result.setComment(comments);
}
}
return result;
}
}
// TODO Call Parser's parseLine() here to attempt to parse, catch any exceptions
return null;
}
The original parseLine that is overridden, but still used is:
public ParserResult parseLine(int lineIndex) {
String[] tokens = lines.get(lineIndex).split(",");
ParserResult result = new ParserResult(Integer.parseInt(tokens[0]),
tokens[1], Float.parseFloat(tokens[2]));
result.setEmail(tokens[3]);
return result;
}
Here is the main() file:
public static void main(String[] args){
// TODO Change the line below to use ImprovedParser
Parser parser = null;
try {
parser = new ImprovedParser(args[0]);
} catch (FileNotFoundException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
System.exit(-1);
}
List<ParserResult> results = parser.parse();
int count = results.size();
double sum = 0.0;
for (ParserResult result : results) {
sum += result.getGrade();
}
System.out.println("Number of valid input lines: " + results.size());
System.out.println("Number of invalid input lines: "
+ (parser.getLineCount() - results.size()));
System.out.println("Average grade: " + sum / count);
for (ParserResult result : results) {
System.out.println(result);
}
}
Lastly, here is the .txt file that is being read:
# student_id,name,grade,email
1234,Bob,92.0,bob#test.edu
4321,Alice,95.0,alice#test.edu
1111,Eve,80.0,eve#test.edu
1121,Barry,85.0,barrytest.edu
1131,Harry,86.0,h#rry#test.edu
1121,Larry,87.0,larry#test.edu
1141,Jim Song,88.0,jim#song.edu
1151,Jerry,77.0,jerry#test.net
1161,James,65.0,james#test.com
The last six inputs should cause exceptions, but I can't figure out how to organize it to work. The code ignores the line with # symbol.
Here is a sample successful output:
Number of valid input lines: 3
Number of invalid input lines: 0
Average grade: 89.0
1234, 92.0, Bob, bob#test.edu,
4321, 95.0, Alice, alice#test.edu,
1111, 80.0, Eve, eve#test.edu,
The major changes should be in the orverride method
Please help if you can, I sit at my desk still pondering possibilities, and your help will be most-appreciated.

Assuming ParseException has an error field being an int and someMethod() that throws ParseException:
try {
someMethod();
} catch (final ParseExeption ex) {
if (ex.getError() == ParseException.SOME_ERROR) {
// do something
} else if (ex.getError() == ParseException.OTHER_ERROR) {
// do something else
}
}
Note that it's usually better to use specific exceptions for specific error, something like SomeErrorParseException, OtherErrorParseException, ... (those can extends ParseException if you want) and try-catch like this:
try {
someMethod();
} catch (final SomeErrorParseException ex) {
// do something
} catch (final OtherErrorParseException ex) {
// do something else
}
Some reading: http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html

It seems that there is no code to actually cause the catch clause in the first place. Try adding a throw new ParserException(STUFF_HERE); when an error has been detected while reading the file.

Related

how to validate Nim should contain 10 digits?

I have made that what is entered must be int and must be positive and now I want to add validation so that the number entered must contain 10 digits
try {
nim = Integer.parseInt(txtNIM.getText());
} catch (NumberFormatException e) {
throw new numberException();
}if (nim < 0) {
throw new PositiveException();
}
try {
nimStr=txtNIM.getText();
if(nimStr.length() !=10){
throw new numberLengthNotTenException(); //this is a custom exception that
//needs to be created outside by
//yourself
// or else you can just print something to console directly and not throw an error
}
else{
nim = Integer.parseInt(nimStr);
}
}
catch (NumberFormatException e) {
throw new numberException();
}
catch(numberLengthNotTenException e){ //add this if you want to throw custom exception
System.out.println(e);
}
if (nim < 0) {
throw new PositiveException();
}
how to create custom exception
Utilize the String#matches() method with a Regular Expression (RegEx) however, you should keep in mind that a 10 digit number can potentially exceed the Integer MAX_VALUE of 2147483647 and will throw an exception, therefore your Integer variable should be of a Long Integer data type and the numerical string be parsed as such with Long.parseLong():
String nimStrg = txtNIM.getText();
long nim;
/* The string numerical value must be no more
and no less than ten digits and can not
start with zero (0). */
if (!nimStrg.matches("^[1-9][0-9]{9}$")) {
System.out.println("Invalid Numerical Value!");
// exit mechanism here if it's required...
}
else {
nim = Long.parseLong(nimStrg);
}
try {
int count = 0;
nim = Integer.parseInt(txtNIM.getText());
} catch (NumberFormatException e) {
throw new numberException();
}if (nim < 0) {
throw new PositiveException();
}
int nim1 = nim;
for (nim1 != 0; nim1 /= 10, ++count) {
}
if (count < 10) {
throw new PositiveException();
}
count variable will count the total digits of the number

Why is my code skipping over certain elements in a txt file?

I'm currently working on an assignment that requires me to build a small database for an imaginary toy company. They sell four different types of toys, with all of their toy's data in a single text file. Different toys have varying attributes to them.
My job is to read every line of the text file, find out what toy it is based on it's serial number, create a new instance of that toy, and load it into an array list of Toys.
Here are some examples of a line in the .txt file for every type of toy.
Animal
2835360879;Cow;Game Assassin;19.52;3;7;Plastic;M
Puzzle
4353818087;Eight queens puzzle;Gamescape;15.69;5;6;C
Figure
1147205649;Ninja Turtles;Gamezoid;46.15;10;6;A
Board Game
7235647474;13 Dead End Drive;Game Assassin;55.18;10;9;1-8;Emeli Davis
The following method is in charge of parsing through the text file, to create new instances of Toy, and to add them into the Array List
public void loadData() {
try {
File dataFile = new File("res/toys.txt");
if (dataFile.createNewFile()) {
System.out.println("Data file created!");
}
else {
Scanner readData = new Scanner(dataFile);
readData.useDelimiter(";"); // sets semicolons as the delimiter
while(readData.hasNext()) {
sn = readData.nextDouble(); // reads the next double (serial number) on each line
category = categoryHandler(sn); // setting and returning value for category based on the serial number
nm = readData.next(); // initializes the name of the toy
brd = readData.next();
prc = readData.nextDouble();
availableCnt = readData.nextInt();
ageApp = readData.nextInt();
// creates a new object, dependant on the category
switch(category) {
case "Figures":
char classification = readData.next().charAt(0);
Figure figures = new Figure(sn, nm, brd, prc, availableCnt, ageApp, classification);
data.add(figures);
break;
case "Animals":
String material = readData.next();
char size = readData.next().charAt(0);
Animal animals = new Animal(sn, nm, brd, prc, availableCnt, ageApp, material, size);
data.add(animals);
break;
case "Puzzles":
char puzzleType = readData.next().charAt(0);
Puzzle puzzles = new Puzzle(sn, nm, brd, prc, availableCnt, ageApp, puzzleType);
data.add(puzzles);
break;
case "Board Games":
String playerCount = readData.next(); // holds the player count as a string
int minPlayers = Integer.parseInt(playerCount.substring(0, 1)); // holds the first integer
int maxPlayers = Integer.parseInt(playerCount.substring(playerCount.length() - 1, playerCount.length())); // holds the second integer
String designers = "";
BoardGame boardGames = new BoardGame(sn, nm, brd, prc, availableCnt, ageApp, minPlayers, maxPlayers, designers);
data.add(boardGames);
break;
default:
System.out.println("Invalid toy type selected!");
}
if (readData.hasNext()) {
readData.nextLine(); // skips to the next line if there's a line to skip to
}
}
readData.close();
}
}
catch (IOException e) {
System.out.println("An error occured.");
e.printStackTrace();
}
}
The following method is in charge of categorizing the toy type.
public String categoryHandler(double serialNumber) {
String serialNumCheck = Double.toString(serialNumber); // converting serial number to string to allow the first digit to be checked
double firstDigit;
// setting up the first digit, checking to see if it's zero.
if (serialNumCheck.length() == 12) {
firstDigit = 0;
}
else {
firstDigit = Double.parseDouble(Double.toString(serialNumber).substring(0, 1));
}
// conditionals
if (firstDigit == 0 || firstDigit == 1) {
category = "Figures";
}
else if (firstDigit == 2 || firstDigit == 3) {
category = "Animals";
}
else if (firstDigit == 4 || firstDigit == 5 || firstDigit == 6) {
category = "Puzzles";
}
else if (firstDigit == 7 || firstDigit == 8 || firstDigit == 9) {
category = "Board Games";
}
// this condition should not be possible to achieve, unless the first digit is negative. Still have it just in case.
else {
System.out.println("Invalid serial number created!");
category = "";
}
return category;
}
After running the loadData() method, my array list only contains 128 toys, instead of the expected 225. Almost all of them are categorized properly, but a few toys are not, at seemingly at random indices.
I suspect it has something to with readData.nextLine() at the end of the loadData() method. The problem is that when I remove the line, the program throws a NullPointerException as there nothing left to scan on the current line, so no Toy can be created.
At this point I'm fairly lost as to what is causing this bug.
Some guidance would be appreciated.

Retrieving Unknown Value using Jsoup

I'm attempting to pull the 'Total Cash Flow From Operating Activities' figure from Yahoo Finance. The variable "s" can be any symbol in the SP500. For the most part, the desired output occurs. However, in some cases, like for AAPL, I can't figure out what it's printing or where it came from.
If "s" is A, the output is 711000000. Correct.
If "s" is AA, the output is 1674000000. Correct.
However, if "s" is AAPL, the output is -416542144. No clue where that comes from.
public class CashFlowStatement {
String cashFromOperatingActivities = "Total Cash Flow From Operating Activities";
public CashFlowStatement(String s) {
String cashFlowStatementURL = ("https://finance.yahoo.com/q/cf?s="+s+"+Cash+Flow&annual");
String cashFlowStatementTableName = "table.yfnc_tabledata1";
boolean foundLine = false;
String line;
int line2;
try {
Document doc = Jsoup.connect(cashFlowStatementURL).get();
for (Element table : doc.select(cashFlowStatementTableName)) {
for (Element row : table.select("tr")) {
if(foundLine == false) {
Elements tds = row.select("td");
for( int j = 0; j < tds.size() - 1; j++) {
if(tds.get(j).text().equals(cashFromOperatingActivities)) {
line = tds.get(j+1).text().replaceAll(",","");
line = line.substring(0,(line.length())-2);
line2 = Integer.parseInt(line)*1000;
System.out.println(line2);
foundLine = true;
}
}
}
}
}
}
catch (IOException ex) {
ex.printStackTrace();
}
catch (NumberFormatException ex) {
ex.printStackTrace();
}
}
}
You have an OVERFLOW! The value from the table is 59,713,000. When you multiply it by 1000 - line2 = Integer.parseInt(line)*1000; you get a number which is greater than MAXINT, thus the negative value. Try use long instead int for line2.

while loop with exception handling

This is my first time using exception handling so be gentle. I have a simple blob class that accepts an ID, the id must be between 30 and 50 or else an exception is thrown.
public class Blob {
int id;
public Blob() {
}
public Blob(int id) throws Exception {
this.id = id;
if (id < 30 || id > 50)
throw new Exception ("id = " +id+ ", must be between 30 and 50 inclusive");
}
}
It should prompt the user to enter an id, and throw the exception if it's not between 30 and 50, and should continue until the user enters a valid input and then simply displays the id number.
public class BlobCreator {
public static void main(String[] args) {
int id;
Scanner scan = new Scanner(System.in);
System.out.println("Enter ID number: ");
id = scan.nextInt();
do {
try {
Blob b = new Blob(id);
}
catch (Exception e) {
System.out.println(e);
}
System.out.println("Enter a different ID: ");
id = scan.nextInt();
}
while(true);
}
System.out.println("Blob ID: " +id);
}
I think that I am using the throw and catch correctly, but my loop isn't working correctly so I think that should be a simple fix but I can't get it just right. Also is using a while loop like I have the best way for this situation or is there a better way to loop through throw and catch?
Thanks for any and all help
You should place the break; after the code is executed successfully.
do {
try {
Blob b = new Blob(id);
break;
}
catch (Exception e) {
System.out.println(e);
}
System.out.println("Enter a different ID: ");
id = scan.nextInt();
} while(true);
So each time the loop would reach the end of its body, it would break out of the loop. You only should break after the blob is created successfully. Although I dont see why you put a break anyway. The while loop can check if the entered input was valid and simply stop the loop.
I modified the while in a do-while loop... By using true the loop will run forever, unless no exception is thrown by the constructor... This makes the code more generic (if you modify the conditions of the blob-construction, you don't have to modify the condition of the while loop).
Sorry, its kind of late to the party. Hope users who endup here may find this useful.
The use of break keyword is discouraged
Here is a very simple implementation to break away after implementing a retry mechanism
This iterates over the loop for the specified number of times and also if the exception still persists, then the exception is thrown. This can be leveraged for an actual real world scenario where the resttemplate might actually result in IO/Network errors and can be retried in those cases
public class TestClass {
public static void main(String[] args) throws Exception {
try {
int c = anotherM();
System.out.println("Now the value is" + c);
} catch (Exception e) {
System.out.println("Inside" + e);
}
}
public static int anotherM() throws Exception {
int i = 4;
Exception ex = null;
while (i > 0) {
try {
System.out.println("print i" + i);
throw new IOException();
// return i;
} catch (Exception e) {
System.out.println(e);
i--;
if (i == 1) {
ex = new Exception("ttt");
}
}
}
if (ex != null) {
throw new Exception("all new");
} else {
return i;
}
}
}

Calling Two Different Methods into One Method in Java

I wish to:
Reading in two files
Split the files into individual strings
Compare the two string lists and retrieve strings that are unique to a file.
At the moment I am running in to the problem of finding a way to call the two methods used to call in the files (one for each file) to the same method in order to be compared.
Both methods use a try-catch-while statement and if I try to read all of the entries after the while statement only a single is shown and not the entire list.
Is there a way to send parts of both methods as parameter to a single new method?
Here is the code for the program. I know that there are problems with the way that I am doing the program, but I am only doing it the way that I was taught.
File mainEmails = new File("Testrun.txt");
Scanner inputScanner = null;
int counter = 1;
String fullName = null;
String position = null;
String companyName = null;
String telNumber = null;
String emailAddress = null;
try
{
inputScanner = new Scanner(mainEmails);
}
catch(FileNotFoundException e)
{
System.out.println("File has not been found.");
}
while (inputScanner.hasNextLine())
{
String nextLine = inputScanner.nextLine();
String [] splitFile = nextLine.split(",");
for (int i = 0; i <splitFile.length;i++)
{
if(i==0)
{
fullName = splitFile[0];
}
else if(i==1)
{
position = splitFile[1];
}
else if(i==2)
{
companyName = splitFile[2];
}
else if(i==3)
{
telNumber = splitFile[3];
}
else if(i==4)
{
emailAddress = splitFile[4];
}
else if(splitFile[i] == null)
{
System.out.println("You have failed!");
}
}
}
public static void deletionList()
{
File deletionEmails = new File("Testrun1.txt");
Scanner inputScanner1 = null;
String deletionfullName = null;
String deletionposition = null;
String deletioncompanyName= null;
String deletiontelNumber = null;
String deletionemailAddress = null;
try
{
inputScanner1 = new Scanner(deletionEmails);
}
catch(FileNotFoundException e)
{
System.out.println("File has not been found.");
}
while (inputScanner1.hasNextLine())
{
String deletionnextLine = inputScanner1.nextLine();
String [] deletionsplitFile = deletionnextLine.split(",");
for (int i = 0; i <deletionsplitFile.length;i++)
{
if(i==0)
{
deletionfullName = deletionsplitFile[0];
}
else if(i==1)
{
deletionposition = deletionsplitFile[1];
}
else if(i==2)
{
deletioncompanyName = deletionsplitFile[2];
}
else if(i==3)
{
deletiontelNumber = deletionsplitFile[3];
}
else if(i==4)
{
deletionemailAddress = deletionsplitFile[4];
}
else if(deletionsplitFile[i] == null)
{
System.out.println("You have failed!");
}
}
}
}
What I am trying to do is to take the fullName, emailAddress from the first split and deletionfullName and deletionemailAddress from the second split and compare the first and second of each, respectively. Each file will have a number of fields in it, and I am only interested in the fullName and emailAddress fields.
It is quite confusing to understand how you are trying to implement your solution, so may I suggest you look at a different way of doing the whole read-and-compare process. For example, I would suggest doing something like this... (in psuedocode)
public void compareFiles(String file1, String file2){
// Read the lines of each file into String[] arrays
String[] file1Lines = readAndSplitIntoLines(file1);
String[] file2Lines = readAndSplitIntoLines(file2);
// compare the lines
for (int x=0;x<file1Lines.length;x++){
for (int y=0;y<file2Lines.length;y++){
if (file1Lines[x].equals(file2Lines[y])){
// match. set it to null
file1Lines[x] = null;
file2Lines[y] = null;
// break out of the inner loop and start comparing the next line
break;
}
}
// remove the duplicates (which are now null values), creating a smaller array of uniques.
String[] newFile1 = shrinkArrayByRemovingNulls(file1Lines);
String[] newFile2 = shrinkArrayByRemovingNulls(file2Lines);
}
Besides the fact that your question is not very clear, you have at least one glaring problem:
DO NOT use exception handling for logic! Exception handling should be only for exceptions.
Secondly, think about what you are really looking to do. In pseudocode it would look something like this:
list1 = split(file(name1).read())
list2 = split(file(name2).read())
list3 = unique(list1, list2)
What does your code look like?

Categories

Resources