I have a below method which does URL decoding on the value passed along with using charset.
public String decodeValue(String value, Charset charset) {
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
// log error
return null;
}
}
return value;
}
Now if URLDecoder.decode line throws UnsupportedEncodingException first time then I want to run same value against below three lines:
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
value = URLDecoder.decode(value, charset.name());
And if then again URLDecoder.decode line throws exception second time, then I will log the error but only second time and return null value otherwise return the value which is decoded.
What is the best and elegant way to do this?
The easiest way is to make a private version of your function signature which includes an extra flag.
private String decodeValue(String value, Charset charset, boolean isFirstTime) {
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
if (isFirstTime) {
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
return decodeValue(value, charset.name(), false);
} else {
// log error
return null;
}
}
}
return value;
}
Then, just pass true the first time and false in the recursive call. Inside the function, only execute the next three lines if true is passed.
The public version can pass true.
public String decodeValue(String value, Charset charset) {
decodeValue(value, charset, true);
}
While it isn't recursive, you could make use of a while loop and a flag.
public String decode(String value, Charset charset) {
boolean first = true;
while(!Strings.isNullOrEmpty(value)) {
try {
return value = URLDecoder.decode(value, charset);
} catch (UnsupportedEncodingException e) {
if(first == false) {
// Log error.
return null;
}
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B");
}
first = false;
}
return value;
}
Here you go :
public String decode(String value, Charset charset) {
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
try {
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
// log error
return null;
}
}
}
return value;
}
Hope this solves your problem.
Adding a flag is one option. Yes, it is the easier one; but many people argue that having flags is simply spoken: bad practice.
You simply try to minimize those things.
In other words: if you have a method that should behave differently for the first and subsequent calls; consider creating two methods there. Of course, you avoid code duplication as far as possible, but unless it becomes to costly, you should at least consider avoiding such flag arguments, too.
Here is version without extra flags, duplicated code, recursion and loops:
public String decodeValue(final String value, Charset charset) throws UnsupportedEncodingException {
String result;
if (!Strings.isNullOrEmpty(value)) {
UnsupportedEncodingException[] lastException = new UnsupportedEncodingException[1];
result = Stream.<Function<String, String>>of(
Function.identity(),
s -> {
s = s.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
s = s.replaceAll("\\+", "%2B");
return s;
})
.map(f -> f.apply(value))
.map(appliedValue -> {
try {
return URLDecoder.decode(appliedValue, charset.name());
} catch (UnsupportedEncodingException e) {
lastException[0] = e;
return null;
}
})
.filter(Objects::nonNull)
.findFirst()
.orElseThrow(() -> lastException[0]);
}
return result;
}
Here I just take stream with 2 functions: identity and function making string correction. Then I apply these functions to initial string and try to decode. If first attempt is successful then code will not apply correction function and just return correct result. If decoder throws exception after value correction then "findFirst" will not find any value. Then we throw last caught exception.
Related
I have a list of strings, each of which is represents a date. I'd like to map this list into a list of DateTime objects; however, if any of the strings are invalid (throws an exception) I'd like to log an error but not add it to the final List. Is there a way to do both the filtering and mapping at the same time?
This is what I currently have:
List<String> dateStrs = ...;
dateStrs.stream().filter(s -> {
try {
dateTimeFormatter.parseDateTime(s);
return true;
} catch (Exception e) {
log.error("Illegal format");
return false;
}
}.map(s -> {
return dateTimeFormatter.parseDateTime(s);
}.collect(...);
Is there any way to do this so that I don't have to parseDateTime twice for each element?
Thanks
To my opinion, it would be more idiomatically correct to use flatMap here:
dateStrs.stream().flatMap(s -> {
try {
return Stream.of(dateTimeFormatter.parseDateTime(s));
} catch (Exception e) {
return Stream.empty();
}
}).collect(...);
Here you can do everything in single operation.
Do the operations in the opposite order.
List<String> dateStrs = ...;
dateStrs.stream().map(s -> {
try {
return dateTimeFormatter.parseDateTime(s);
} catch (Exception e) {
return null;
}
}).filter(d -> d != null).collect(...);
(Too late I realize this is essentially the same as #wero but hopefully the code will make it clear.)
Updating for Java 9
Similar to Tagir's solution, you can map to an Optional, logging an error when the conversion fails to produce a value. Then, using the new Optional::stream method, you can flatMap on the optional, removing the failed conversions (empty optionals) from the stream.
dateStrs.stream()
.map(s -> {
try {
return Optional.of(dateTimeFormatter.parseDateTime(s));
} catch (Exception e) {
log.error("Illegal format: " + s);
return Optional.empty();
}
})
.flatMap(Optional::stream)
.collect(...);
You could first map the string to its parsed date. If you encounter a invalid date string, you log it and return null.
Then in a second step you filter for non null dates.
I am load the properties file and get the value from that file but when i using "Properties" class and getProperty(key) method, it was return null value.
code:
public class LoadPropertiesFile {
public static String getProperty (String key, String filePath) {
Properties properties = new Properties();
InputStream inputStream = null;
String value = null;
try {
String appHome = ConfigUtil.getApplicationHome() + filePath;
inputStream = new FileInputStream(appHome);
//load a properties file
properties.load(inputStream);
//get the property value
System.out.println(properties.getProperty("7")); //print **Unlock**
System.err.println(key); //print **7**
System.out.println(value); //print **null**
value = properties.getProperty(key);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
return value;
}
}
Output:
Unlock
7
null
Property File:
2=Interactive
3=Network
4=Batch
5=Service
7=Unlock
8=Network Cleartext
10=Remote Desktop
11=Logon with cached credentials
call method:
logonType = new LoadPropertiesFile().getProperty("7", "path");
When i call that method it will return null value only. please help me guys.
You are initalizing value with null.
String value = null;
And you assign it after printing it:
System.out.println(value);
value = properties.getProperty(key);
Output: null
So value can only be null when you print it, as you never change its value until System.out.println(value);.
Just switch those two statements:
value = properties.getProperty(key);
System.out.println(value);
Output: unlock
Edit
properties.getProperty(key) may return null too, but only if there is no such key in its table, otherwise it will return the assigned value, in your example unlock.
See the API Documentation on this for more details:
public String getProperty(String key)
Searches for the property with the specified key in this property list. If the key is not found in
this property list, the default property list, and its defaults,
recursively, are then checked. The method returns null if the property
is not found.
http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#getProperty(java.lang.String)
System.out.println(value); //print **null**
value = properties.getProperty(key);
Switch these two lines and initialize value before printing it:
value = properties.getProperty(key);
System.out.println(value); //print Unlock
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'm trying to do something reallllly simple that apparently is extremely difficult in android.
I just want to compare two strings to see if they are equal.
I have a temp variable with the value "Location"
I have debugged this and it does indeed contain Location...
So I tried this at first
if(temp == "Location") { //do something }
But I already know that doesn't work. I then tried all the possible functions for a string such as:
.equals
.contains
.ignoreCaseEquals
etc...
If anyone has any idea what to do please help. This is really getting annoying.
EDIT:
Here is the function where I'm comparing the strings for those of you who want to see.
public String[] getData(){
try {
int tempGroupCount = 0;
URL food_url = new URL (Constants.SERVER_DINING);
BufferedReader my_buffer = new BufferedReader(new InputStreamReader(food_url.openStream()));
temp = my_buffer.readLine();
// prime read
while (temp != null ){
// check to see if readline equals Location
Log.w("HERasdfsafdsafdsafE", temp);
// start a new location
if (temp.equals("Location")
{
groups[tempGroupCount] = temp;
tempGroupCount++;
}
Log.w("HERasdfsafdsafdsafE", temp);
//start for-loop to test to get child info
//for(temp = my_buffer.readLine(); temp != "Location" && temp != null; groupCount++, childrenCount++){
//children[groupCount][childrenCount] = temp;
//}
temp = my_buffer.readLine();
}
my_buffer.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("IO EXCEPTION", "Exception occured in MyExpandableListAdapter:" + e.toString());
}
return groups;
}
equals does work. If temp.equals("Location") returns false, then your temp variable does not refer to a string with the value "Location".
There may be unprintable characters or other oddities about the string - I suggest you look at the length of the string to check. Alternatively, there can be other characters which look like the ASCII characters, but aren't. In the debugger, try examining the array and get at the underlying char array - check the Unicode value of each character.
if(temp.equals("Location"))
{
//your code here
}
does not work
try this
if(temp.contains("Location"))
{
//your code here
}
try like
if(temp.equals("Location")) { //do something }
and
while (!temp.equals("")){
if your variable temp is a String, you can also used the method compareTo(String).
if (temp.compareTo("Location") == 0)
{
//do something
}
I am doing same scenario , its working fine.
String result = responsePrimitiveData.toString();
if(!result.equals("0")){
}
Try doing this:
if (temp.toLowerCase().compareTo("location") == 0)
public String[] getData(){
try {
int tempGroupCount = 0;
URL food_url = new URL (Constants.SERVER_DINING);
BufferedReader my_buffer = new BufferedReader(new InputStreamReader(food_url.openStream()));
temp = my_buffer.readLine();
// prime read
while (temp != null ){
// check to see if readline equals Location
Log.w("HERasdfsafdsafdsafE", temp);
// start a new location
if (temp.toString().equalsIgnoreCase("Location")
{
groups[tempGroupCount] = temp;
tempGroupCount++;
}
Log.w("HERasdfsafdsafdsafE", temp);
//start for-loop to test to get child info
//for(temp = my_buffer.readLine(); temp != "Location" && temp != null; groupCount++, childrenCount++){
//children[groupCount][childrenCount] = temp;
//}
temp = my_buffer.readLine();
}
my_buffer.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("IO EXCEPTION", "Exception occured in MyExpandableListAdapter:" + e.toString());
}
return groups;
}
first try to convert "temp" into string then compare it, apply this may helps you
you may try the following to find out where your problem is.
final String LOCATION = "Location"; // just to make sure we use the very same character sequence
if (temp.equals(LOCATION)
{
/* your code here */
}
else
{
System.out.println("Location : " + Arrays.toString(LOCATION.getBytes(Charset.forName("UTF-8"))));
System.out.println("temp : " + Arrays.toString(temp.getBytes(Charset.forName("UTF-8"))));
}
This should print the byte representation of both Strings to standard out. If equals() returns false, the strings differ. Because of unprintable characters or similar looking characters it's sometimes difficult to find the difference. But the byte representation should show you.
(I'm not an android programmer, so I hope the functions exist on android JVM. And sorry for any typos and missing brackets - if any ;-)
Let's say I can a set of statements:
try {
String a = getProperty("a");
String b = getProperty("b");
String c = getProperty("c");
} catch(Exception e) {
}
Now, lets say property b was not found and the function throws an exception. In this case, how would I just continue or perhaps set b to null without having to write a try-catch block for each property? I mean, a,b,c exist but sometime they might not be found at all during which an exception is thrown.
Assuming you can't change the function so that it returns null when the property isn't found, you are kind of stuck wrapping everything in its own try catch block -- especially if you want for every value that can be retrieved to be retrieved (as opposed to letting the first value that fails cancel the whole operation.)
If you have a lot of these properties to retrieve, perhaps it would be cleaner to write a helper method to use:
String getPropertySafely(String key) {
try {
return getProperty(key);
} catch (Exception e) {
return null;
}
}
You have to put a try-catch around each statement. There is no continue (like there is in ON ERROR ... RESUME blocks in VB). Instead of:
String a = null;
try {
a = getProperty("a");
} catch(Exception e) {
...
}
String b = null;
try {
b = getProperty("b");
} catch(Exception e) {
...
}
String c = null;
try {
c = getProperty("c");
} catch(Exception e) {
...
}
you could write:
public String getPropertyNoException(String name) {
try {
return getProperty(name);
} catch (Exception e) {
return null;
}
}
Personally I think a getProperty() is a poor candidate for throwing exceptions just for all this extra boilerplate required
Since you are using the same function each time you might be able to put this in a loop:
String[] abc = new String[3];
String[] param = {"a", "b", "c"};
for (int i = 0; i < 3; i++) {
try {
abc[i] = getProperty(param[i]);
} catch(Exception e) {
}
}
but this is rather contrived and would only be useful for a large number of properties. I suspect you will have to simple write 3 try-catch.
You should reconsider how getProperty is handled if you plan to use many of them because there isn't a plain way to do it.
You can exploit finally statement but you still need a try-catch for every call.