I'm using the Android SAX parser to search for entries in a rather large (6MB) XML file. I'm basically using a derivative of the code shown in listing 8 here. The question I have is how do I stop parsing once my match has been found? The code shown continues parsing through the end of the file but I want to stop before then. Is this possible or do I need to use something other than SAX (e.g. XmlPullParser?)
Generate an ArithmeticException and catch it !
if (condition) { int a=1; a/=0; }
...
try {
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
}
catch (ArithmeticException e) {
return true;
}
That's awful but it works...
Well DiskCrasher,
Every Sax parser will work till the end generally, But if you still want to quit it while its in the middle of the work, you can always check condition and use the return statement.
But Far better way of selective parsing would be to use the XML PullParser, Coz this parser will in general work on the fly and give you data without loading the whole file. This way you can check condition and exit the loop anytime without even need to use large memory chunks...
Hope this is somehow helpful to you!!!
You can throw an exception when you get a match. The exception can capture the match info and will be propagated to the original parse() caller. Catch the exception and test whether it is one based on getting a match or a true parsing error and process accordingly.
Related
I am new to android development. In the overriden onCreate() method of my activity, I perform some operations. For ex. check if SharedPreference is already available and then route to other activity. How do I perform exception handling on this onCreate() method. Is it the right way to wrap the contents in a try catch and display the error dialog on exception?
If the exceptions are not handled properly, in my case the onCreate() method, the app crashes with message:
Unfortunately your application stopped working
On searching in the internet, I found that UncaughtExceptionHandler could be used to handle it. Any sample implementation and how to call it from all my activities would be helpful.
THat's the wrong way to go about it. Instead, go into your logcat. Read the stack trace of the exception. Figure out what you did wrong. Fix it. Just catching exceptions is a horrible practice unless you're catching a specific exception for a specific reason- its very unlikely your app is in a state where it can continue correctly. Don't be lazy, track down your bug and fix it.
With something like this you can catch a generic Exception in your onCreate() method:
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
try {
// do whatever you need
} catch (Exception e) {
e.printStackTrace();
}
}
Exception catching can be used with many goals. An interesting one is to catch particular expected exceptions to fix some problems (for example setting a generic value into a variable otherwise null after occurring an error).
The general purpose however is to avoid that an error causes a problem or in the worst case a crash of your application. Depending oh what kind of software you are developing, a crash may represents a little problem (like in an Android app), a very big one (like in airplane's softwares or power plants' softwares).
We can identify two kind of exceptions.
The first type are those exceptions specific to definite problems. They have to be declared into methods signature, so you are encouraged or obbligated to manage these exceptions and their relative problems. These exceptions represent an error that should probably occur during particular code execution, like a parsing error, or an input output error. For this type of problems we have particular exceptions, to catch and easily manage them (for example as previously said to init a variable with a default value after an error).
The second type of those exception represents instead some generic problems that can occur during program execution. They are a big and generic set and generally their probability of occurring is low. For this reason you are not obbligated to manage them. The main example of this type is the general Exception class.
So an catching an Exception is not the right approach to solve a bug, as suggested by Gabe Sechan.
Catching a generic Exception in the main() Java method can be a way, for example, to show a default human readable error to the user if nothing else is available.
Or could be a way to keep the failing of the current operation reducing crash probability.
Now, in Android we can't act directly on the main() method. onCreate() method is executed and exited so catching here a generic Exception has no much sense. Obviously it depends also on what you do in your onCreate() method and what you want to do if an error occurs. You could do some strange stuff (is very defined what you should do in the onCreate() method) and you could need to manage a big set of problems only showing an error, so it has more sense catch only a generic Exception than a lot of particular exceptions to make the same thing in each catch block.
If you want to achieve this goal (a message showed for all the errors occurred during onCreate() execution, made Activity by Activity) this is the right approach.
If instead what you want to achieve is to intercept all of the errors that are generated during all of your app execution, a good approach could be the UncaughtExceptionHandler, that act similarly to catch a generic Excepetion into a Java main() method. At this level an interesting approach is described here.
For more infos about exceptions you can read this and this.
I have some XML in an Android application where XmlPullParser is the recommended solution for binding that XML to data model classes. The Android documentation for XmlPullParser is fairly good except for how to deal with inter element whitespace. The recommended approach is to detect low-level IGNORABLE_WHITESPACE parsing events and skip over those events. However for the XML I am trying to accept, this approach is not working for me. I never see the low level IGNORABLE_WHITESPACE events occurring. Which has me believing that I do not correctly understand some aspect of my particular use case, either XmlPullParser behavior, acceptable XML, or possibly a configuration issue.
My simplified test case for an XML snippet that I am trying to accept is:
<a> <b></b> </a>
and the code hack I am using to accept this element with the recommended getNextToken() method is:
boolean hasEvent = false;
String desc = null;
while (!hasEvent) {
result = xpp.nextToken();
desc = xpp.getPositionDescription();
Log.i(TAG, String.format("Processing: %s", desc));
switch (result) {
case START_TAG:
case END_TAG:
case END_DOCUMENT:
hasEvent = true;
break;
case TEXT:
// Use a real hack to detect whitespace.
if (desc.contains("TEXT (whitespace)#")) {
hasEvent = false;
} else {
hasEvent = true;
}
break;
default:
break;
}
}
and the result that I see is, essentially: got START_TAG(a), got TEXT (whitespace), got START_TAG(b), got END_TAG(b), got TEXT (whitespace), got END_TAG(a).
So the questions are: what am I not understanding correctly? And how would I accept this sequence without resorting to an ugly hack, something more in keeping with recommended use of XmlPullParser.
I have a hunch that this is questionable XML but it is representative of what I will be presented with, i.e. I cannot control the inter-element whitespace in the input stream.
fwiw, the Simple Framework for XML deals with this input stream without a hiccup and is my preferred approach but that package is very, very messy to use with Gradle and Android Studio due to dependency conflicts with the underlying stax and epp libraries, but that is another issue entirely.
To somewhat answer my own question, I offer up the following for developers who find themselves in my situation at some point. But I very much look forward to even better answers soon.
As for lack of understanding, the first point is that now I understand that I am using a non validating parser. This claim is made in the Android XmlPullParser source code/Javadoc for isWhitespace():
Please note: non-validating parsers are not able to distinguish whitespace and ignorable whitespace, except from whitespace outside the root element. Ignorable whitespace is reported as separate event, which is exposed via nextToken only.
This leads me to believe that JAXB and Simple are validating parsers and can deal with this inter-element whitespace in stride whereas I now must deal with it explicitly, much to my chagrin.
A second point that falls under the lack of understanding umbrella is that Android's XmlPullParser can only create validating parsers by providing a "schema" to back the validation, something that is pretty much out of my control for this instance.
As for a more elegant way to deal with inter-element whitespace, my answer would be to have two methods: getNextElement() which will return the next START_TAG or END_TAG event but throw away all TEXT events where the text is whitespace, anything else is deemed a parsing error; the other method would be getNextText() which will return text from either TEXT or CDSECT parsing events and report any other event as an error.
As I said, I'm looking forward to better answers.
I am still fairly new to programming, so there are some things I learn from observing but do not fully understand. The Try-Catch is one of these things. From what I have researched, the try statement allows me to define a block of code to be tested for errors, and the catch statement allows me to define a block of code to be executed if an error occurs in the try block.
I get that. And I have tried to use Try-Catch in situations where I was receiving exception errors that crashed my applications. The Try-Catch seemed to prevent (stop) the crashing. But here is my question, is it OK to have an application that constantly catches an exception error?
For example, I am working with EditText widget. I want the input values for the EditText to represent currency, so I applied android:inputType="numberDecimal". The issue I learned with this is that this attribute allows any number of values after the decimal. This is when I came up with an idea of updating the EditText programmically with the proper format, using something like DecimalFormat.
I am not posting my entire code, but here is the piece that I am curious about.
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
DecimalFormat format = new DecimalFormat("0.00");
if (etBill.getText().toString() != null &&
etBill.getText().toString().length() > 0) {
try {
doubleBill = Double.parseDouble(etBill.getText().toString());
strFormatted = format.format(doubleBill);
Log.d(TAG, "unformatted(" + doubleBill + ")" +
" // formatted(" + strFormatted + ")");
//etBill.setText("$" + strFormatted, TextView.BufferType.EDITABLE);
etBill.setText("$" + strFormatted);
} catch (NumberFormatException nfe) {
Log.e(TAG, "FloatingPointParser.parseDouble error");
}
} else {
// values in editText were deleted; hardcode value
doubleBill = 0.0;
strFormatted = format.format(doubleBill);
}
}
And here is the exception error I catch every single time I input a value into my EditText widget.
So my question is, is the Try-Catch a method for me to correct my errors? Is it OK to catch exception errors, such as this NumberFormapException through the life of an application running? Am I using this right? Thanks in advance!
NumberFormatException is a runtime exception and you are catching it correctly. However, instead of just printing something to let you know you have caught it, you should either handle it by re-running through your code or pass the exception up the stack. For example, if a user inputs a number and then this exception is caught, you could prompt them to re-enter a new number. If the number that is throwing this exception is not provided by a user, but by your code, then it indicates you have a logic error somewhere and should fix that to prevent this exception from being thrown in the first place.
In general the exception mechanism should be used for exceptional circumstances - something that usually shouldn't happen. If you have an exception that's being thrown every time you enter a value, that's sort of abusing the mechanism. Usually there's a better way that doesn't involve exceptions. In some cases though, the exception mechanism is the cleanest way of dealing with the situation.
Here's a quote from Effective Java: Programming Language Guide by Josh Bloch:
"Use exceptions only for exceptional conditions. That is, do not use exceptions for control flow, such as catching NoSuchElementException when calling Iterator.next() instead of first checking Iterator.hasNext()."
Exception handling is not only an art but the subject of much discussion/debate. I will try to address the broader points without incurring anyone's wrath.
There are two kinds of exceptions--fault exceptions and contingency exceptions. Fault exceptions are unrecoverable like being unable to connect to a web service that is supposed to be there for your app to function. You log those in your catch block and rethrow to let them bubble to some fault handler. Contingency exceptions are what you described with the number format issue--stuff you can recover from. In this case, you handle things completely in the catch block. You allow the app to recover by prompting for a new input, for example.
By the way, none of that is my own. That strategy comes from Barry Ruzek.
Then there is the issue where people dislike using exceptions for flow control--for good reason. In your case, that would mean using a regular expression in an if statement, for example, to test number format rather than using a potential exception-generating operation. You generally don't want to use exceptions for normal control flow, but you also need to be careful not to let ideology trump a simple solution. There is a balance you will learn with experience.
So you should recover from the exception in your catch block. Or use a different non-exceptional mechanism entirely to manage control flow.
Hope that helps.
Using Try catch in programing is fair enough. But handling errors is different issue. Try catch is just to way catch erronious conditions which can occur in ur program but u may wish to catch it or leave its up to you. Simple example is age is not allowed as floating point number but height is allowed both floating point and decimal number.
i have a situation where i may encounter a possible null, and i don't want my program to crash. it is only happening for a small % of users and i'm not entirely sure why, but i know the section of code that is doing it. basically the isAchieved() is a check that should return a boolean value, but in a few cases it is returning a null. this is part of a scoreloop library and i have a suspicion the bug might be with their code.
rather than getting a force close and exiting the program is there a way to check if this value is going to return a null and simply skip over this section of code if that is the case?
if (_achievements[ltc].isAchieved()) {
// Do stuff for 99.9% of users here, but skip if .isAchieved() would force close
}
boolean checker=false;
try{
checker=_achievements[ltc].isAchieved();
}
catch(NullPointerException e){
}
if (checker) {
//content
}
Did you think about doing that?.
I'm making an Android app, which gets its information from XML files.
I'm filling the information in a database, for easier acces during the program's runtime, thanks to the power of queries.
However it came to my attention, that using Transactions greatly improves speed, so naturally, I want to use that.
My problem is the following tho;
In the idea of abstraction, after parsing all the information of one subject, the information gets send to the correct entity (class), and inside that entity there is a method that will add it in the database. After that, it returns to the parser which continues to read the next subject, which in it's turn will be send to right (and probably different) class again.
This is implemented with a switch statement, with every case pointing to a different class constructor.
If I want to use the speed of transactions, I would need to start a transaction already before the parsing, run through the parsing and query building (as far as I understand, all queries build within the transaction, are collected and in the end all executed as a bunch) and then end the transaction, once the whole file is parsed.
To make this a bit clearer, or faster to read; The code idea would be;
Class parser(){
database.beginTransaction();
try{
// start parsing in a whole different class, which also points to SQL queries (in different classes again) in the entitys with a switch
}catch(Exception e){
database.endTransaction();
}
database.endTransaction();
}
I hope i formulated my question clearly enough.
Kind regards,
Yes, you've got the general idea. However, you need to be careful to mark the transaction as successful when you finish parsing, and also to ensure the transaction is always closed even in the event of an exception.
Example from the docs:
db.beginTransaction();
try {
// do all the parsing in here
...
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}