I'm writing a file reader that returns an object and I'd like it to warn on parse errors and continue to the next record.
The code below is the obvious implementation of this, but involves recursing from inside the catch block. Is there any technical or stylistic reason not to do this?
public RecordType nextRecord() throws IOException{
if (reader == null){
throw new IllegalStateException("Reader closed.");
}
String line = reader.readLine();
if (line == null){
return null;
}else{
try {
return parseRecord(line);
}catch (ParseException pex){
logger.warn("Record ignored due to parse error: "
+ pex.getMessage());
//Note the recursion here
return nextRecord();
}
}
}
I would prefer to use a loop. With recursion, you never know how deep you can safely go.
String line;
while((line = reader.readLine()) != null) {
try {
return parseRecord(line);
}catch (ParseException pex){
logger.warn("Record ignored due to parse error: " + pex);
}
}
return null;
Why not replace the recursion with a loop:
public RecordType nextRecord() throws IOException {
if (reader == null) {
throw new IllegalStateException("Reader closed.");
}
for (;;) {
String line = reader.readLine();
if (line == null) {
return null;
} else {
try {
return parseRecord(line);
} catch (ParseException pex) {
logger.warn("Record ignored due to parse error: "
+ pex.getMessage());
// continue to the next record
}
}
}
}
Stylistically, I find this preferable.
Would it be cleaner to let the ParseException propagate back to the caller? The caller could then decide what to do about it.
What it seems like to me is that whatever is calling your method is going to keep calling it until the method returns null.
I would probably follow the advice of the previous posters and use a loop, however I would look at whatever is calling the method (as it is probably already using a loop), have it skip the line by looking for an exception to be thrown.
Related
I'm currently working on a simple method which converts the content of a file to a string. I saw several topics covering some detail about this question (here). However I can use the try catch or a return do_nothing as mentioned in the previous linked answer. The code:
public static String getStringFromFile(String path) throws EmptyFileException {
String data =null;
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
String line;
while ((line = reader.readLine()) != null) {
data += line +"\n";
}
if (data == null) {
throw new EmptyFileException();
}
}
catch (FileNotFoundException ex) {
showExceptionMessage("File not found");
}
catch (IOException ex) {
showExceptionMessage("Can't read the file");
}
return(data);
}
private static void showExceptionMessage(String message) {
JOptionPane.showMessageDialog(null, message, "ERROR", JOptionPane.ERROR_MESSAGE);
}
So what would be "better" throwing an exception if the file is empty or just using return doNothing() (were doNothing is the function that does nothing, makes sense right? hahah).
Is this a good way to avoid null return?
Yes, always return "existing" object instead of null if you can. Null Object Pattern is a good aproach to avoid that.
So what would be "better" throwing an exception if the file is empty
or just using return doNothing()
In your case throwing an exception is overkill for me. You should throw an exception when you don't expect particular behaviour. Have a look at FileNotFoundException. You always expect that file exists so it's a good choice to throw exception when you can't find this file.
So as metioned above null is bad, so why can't you return empty string? :) In this case it will work like Null Object Pattern, like placeholder :)
This question already has answers here:
Using BufferedReader.readLine() in a while loop properly
(7 answers)
Closed 8 years ago.
I have problem with reading from my socket i read only if value isn't null but it doesnt't works.
#Override
public void run() {
System.out.println("Reading from socket");
while(true){
try {
if(!(br.readLine().equals(null)))read += br.readLine();
} catch (IOException e) {
System.out.println("error " + e);
}
}
}
here is error:
Exception in thread "Thread-4" java.lang.NullPointerException
at connection.CreateConnection.run(CreateConnection.java:61)
at java.lang.Thread.run(Unknown Source)
If br.readLine() returns null, then calling .equals(null) on it will throw an exception - it won't return true. You just want to compare reference identity with null.
Calling .equals(null) is never useful, unless you're testing that your equals implementation works properly :)
Additionally, you'll be skipping every other line by calling readLine() twice on each loop iteration.
You want something like:
String line;
if ((line = br.readLine()) != null) {
read += line;
}
... except that will be painfully slow due to repeated string concatenation. You should almost certainly be using a StringBuilder instead.
Also, doing all of this in a loop which catches IOException seems like a recipe for disaster - if the a call fails, it's very likely that it'll keep failing forever, whereupon your program is basically hung in a tight loop. You should almost certainly stop when you get an exception, rather than keeping going. For example:
try {
String line;
while ((line = reader.readLine()) != null) {
read += line; // Or builder.append(line);
}
} catch (IOException e) {
// Whatever you want to do
}
Finally, consider the value of whitespace, both horizontal and vertical, as well as the benefits of using braces even in single-statement if statements etc. The line if(!(br.readLine().equals(null)))read += br.readLine(); is compact at the expense of readability.
Say you are on the last line of your file, you call br.readLine() to check if it's not null. Your line exists so your test passes. Then you call br.readLine() once again. Unfortunately there is nothing left to read! And you get your exception.
Rewrite your code like that:
#Override
public void run() {
System.out.println("Reading from socket");
String line;
while(true){
try {
line = br.readLine()
if((line != null))read += line;
} catch (IOException e) {
System.out.println("error " + e);
}
}
}
You are calling .equals() on a null object, which causes the null pointer issue I assume. If you want to read with a buffered reader, try doing something like:
String line = reader.readLine();
while(line != null){
System.out.println(line);
line = reader.readLine();
}
This will eliminate the issue of null pointers, and will also stop you from skipping any lines during reading.
Why in many codes written like as:
finally{
if(out!=null){
try{out.close();}
catch(){}
}}
But not:
finally{
try{out.close();}
catch(){}
}
Typically you want to create some kind of stream. This creation could fail, e.g. because a file is missing or an internet connection is not working. So you need to put it into a try-catch-block because it throws a check-exception which you need to handle:
Stream stream = null;
try {
stream = makeNewStream();
// more stuff
} catch(SomeException e) {
// do something with the exception
}
Now you want to be sure, that the stream is closed in the end, no matter what happens. So you add a finally block:
Stream stream = null;
try {
stream = makeNewStream();
// more stuff
} catch(SomeException e) {
} finally {
stream.close()
}
This block will be called in any case, even if your code fails (e.g. stream = makeNewStream(); throws an exception). But if stream = makeNewStream(); throws an exception, the variable stream will be null. So you need to check if stream is null (you cannot call a method on null ;):
finally {
if(stream != null)
stream.close()
}
Now, unfortunately, close() will also throw a checked-exception (which need to be handled), so you have to check this too. And you will end up with something like this:
Stream stream = null;
try {
stream = makeNewStream();
// more stuff
} catch(SomeException e) {
} finally {
if(stream != null) {
try {
stream.close()
} catch(ClosingException e) {
// ignore this
}
}
}
Most developers will just ignore the last exception in the finally block.
I am encountering an error when user doesn't type anything into input statement. I thought of using Try/Catch blocks to instead throw exception to set boolAskRepeat to true which should skip to the end of the code and repeat the loop.
This doesn't work, and I believe I'm missing something but I'm not sure what... It still throws exception saying:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(Unknown Source)
at ITSLab03.main(ITSLab03.java:34)
Which is this line of code: inputStatus = input.readLine().toLowerCase().charAt(0);
What am I doing wrong here?
while (boolAskStatus == true)
{
System.out.print("Employment Status (F or P): ");
try
{
inputStatus = input.readLine().toLowerCase().charAt(0);
if (inputStatus == "f".charAt(0))
{
boolAskStatus = false;
String stringCheckSalary = null;
boolean boolCheckSalary = true;
while (boolCheckSalary == true)
{
// some code
}
outputData(inputName, inputStatus, calculateFullTimePay(inputSalary));
}
else if (inputStatus == "p".charAt(0))
{
// some code
outputData(inputName, inputStatus, calculatePartTimePay(inputRate, inputHours));
}
else boolAskStatus = true;
}
catch (IOException e) { boolAskStatus = true; }
}
You need to catch StringIndexOutOfBoundsException as well (If you observe the stack trace properly this is the exception you are getting)
catch (StringIndexOutOfBoundsException e) {
boolAskStatus = true;
}
(or)
catch Exception which catches all runtime exceptions
catch (Exception e) {
boolAskStatus = true;
}
The normal try catch pattern should look like this:
try
{
// code that is vulnerable to crash
}
catch (Specific-Exception1 e1)
{
// perform action pertaining to this exception
}
catch (Specific-Exception2 e2)
{
// perform action pertaining to this exception
}
....
....
catch (Exception exp) // general exception, all exceptions will be caught
{
// Handle general exceptions. Normally i would end the program or
// inform the user that something unexpected occurred.
}
By using .charAt(0), you are assuming that the String has a length > 0.
You could simplify this a bunch by just doing:
String entry = input.readLine().toLowerCase();
if (entry.startsWith("f")) {
...
}
else if ("entry".startsWith("p")) {
...
}
Your code doesn't work the way you want because input.readLine().toLowerCase().charAt(0) throws a StringIndexOutOfBoundsException, which is not an IOException, so the catch block never gets hit. You can make it work by changing the catch to
catch (StringIndexOutOfBoundsExceptione e) { boolAskStatus = true; }
But...
It's generally not a good idea to base your program's normal behaviour on exception handling. Think of exception throwing as something that could happen, but usually won't. Why not use something like:
final String STATUS_F = "f";
final String STATUS_P = "p";
String fromUser = null;
do {
String rawInput = input.readLine().toLowerCase();
if (rawInput.startsWith(STATUS_F)) {
fromUser = STATUS_F;
} else if (rawInput.startsWith(STATUS_P)) {
fromUser = STATUS_P;
}
} while (fromUser == null);
if (STATUS_F.equals(fromUser)) {
// do something
} else if (STATUS_P.equals(fromUser)) {
// do something else
} else {
// Shouldn't be able to get here!
throw new Exception("WTF!?");
}
It much easier for another person reading this to understand why the program loops and how the loop is controlled, in part because the code that figures out what the user is inputting and the code that decides what to do with that information are separated. Plus, you don't need to deal with exceptions.
I have this line of Code
try {
String txtText = article.getTxtText().toString();
if (StringUtils.hasText(article.getTxtText().toString())){
textPropertyList.add(txtText);
}
String txtLongText = article.getObjLongTextData().toString();
if (StringUtils.hasText(txtLongText)){
textPropertyList.add(txtLongText);
}
String txtShortText = article.getObjShortTeaserData().toString();
if (StringUtils.hasText(txtShortText)) {
textPropertyList.add(txtShortText);
}
} catch (NullPointerException e) {
}
It is possible, that only one of the three properties are set. But if one property isnt set, I get this NullpointerException. I catch it, but then the try-Block isnt continued.
So e.g. if the article.getTxtText() method returns null, I dont get the txtLongText and txtShortText Strings either, although at least one of them has a not empty String set.
So the question is, how can I continue the try-block although there's is an Exception caught?
Thanks a lot.
You should either use 3 try-catch blocks or just use a null-check around every case.
if (article.getTxtText() != null) {
// do part 1
}
if (article.getObjLongTextData() != null) {
// do part 2
}
I would imagine that the correct approach to this is to have three try/catch blocks around each point of code. The whole point of a try block is that you are trying the code as a lump and if it fails anywhere you abandon it. For what you are describing you would need three try/catches around each possible point of failure.
That having been said you are probably better off testing for null rather than relying on exception handling to do that. Exception handling should be for exceptionalm unforeseen events, not for flow control in a program.
If you must do this with exceptions (and I don't think you should), then you need to have 3 separate try/catch blocks:
try {
String txtText = article.getTxtText().toString();
if (StringUtils.hasText(article.getTxtText().toString())){
textPropertyList.add(txtText);
}
} catch (NullPointerException e) {}
try {
String txtLongText = article.getObjLongTextData().toString();
if (StringUtils.hasText(txtLongText)){
textPropertyList.add(txtLongText);
}
} catch (NullPointerException e) {}
try {
String txtShortText = article.getObjShortTeaserData().toString();
if (StringUtils.hasText(txtShortText)) {
textPropertyList.add(txtShortText);
}
} catch (NullPointerException e) {}
Once an exception is thrown in your code you cannot restart execution in the middle of the try block.
Having said that I would always prefer to detect the null pointer with an if test rather than relying on exception handling for this non-exceptional condition.
do defensive programming ,check for nulls.
if ( variable != null ){
...
}
The simplest and better approach from my point of view would be break the try - catch block in three different try-catch block, something like the following :
try {
String txtText = article.getTxtText().toString();
if (StringUtils.hasText(article.getTxtText().toString())){
textPropertyList.add(txtText);
}
} catch (NullPointerException e) {
//Handle Exception
}
try {
String txtLongText = article.getObjLongTextData().toString();
if (StringUtils.hasText(txtLongText)){
textPropertyList.add(txtLongText);
}
} catch (NullPointerException e) {
//Handle Exception
}
try {
String txtShortText = article.getObjShortTeaserData().toString();
if (StringUtils.hasText(txtShortText)) {
textPropertyList.add(txtShortText);
}
} catch (NullPointerException e) {
//Handle Exception
}
I'd recommend a different design:
private void addProperty(Object property, Collection<String> properties) {
if (property == null) {
return;
}
String textProperty = property.toString();
if (StringUtils.hasText()) {
properties.add(textProperty);
}
}
Usage:
addProperty(article.getTxtText());
// ...
Why are you doing this in a try / catch, just use simple if
if ( txtText != null ){
...
}
if ( txtLongText != null ){
...
}