I'm trying to format a phone number which is stored without formatting in a database.
Now currently I just use substring and String concatination to form the formatted String but I'm looking for a cleaner/faster/less memory intensive method. (and I don't mean just using a StringBuilder).
I looked at String.format but that only takes a list of parameters (as in ...) and not a chararray.
I'll toss in my 2 cents after some lookup:
import java.swing.text.MaskFormater;
try {
MaskFormatter formatter = new MaskFormatter("+AA AAA AA AA AA");
formatter.setValueContainsLiteralCharacters(false);
System.err.println(formatter.valueToString("31987365414"));
} catch (ParseException e) {
}
If you want to build a String from char array(s) plus some things (chars, strings, whatever) between them, then StringBuilder is definitely the right way to go, if you don't want to simply concatenate. An important point is to initialize the builder with enough initial capacity so that it doesn't need to reallocate its internals while building.
Related
I have a question regarding the behavior of the NumberFormat:
When I want to translate/parse a formatted String into a Number, then I would like to use NumberFormat, since it provides me with nice presets for thousand and decimal separators. Additionally I would like it to crash, if the provided String is not a valid Number.
An example:
// works as expected
String testInput1 = "3,1415";
NumberFormat germanNumberFormat = NumberFormat.getInstance(Locale.GERMANY);
Number number1 = germanNumberFormat.parse(testInput1);
System.out.println(number1); // prints 3.1415
// does not work as expected, cuts off the number after the 2nd decimal
// separator, expected it to crash with java.lang.NumberFormatException:
// multiple points
String testInput2 = "3,14,15";
Number number2 = germanNumberFormat.parse(testInput2);
System.out.println(number2); // prints 3.14
I currently use Double.parseDouble(String s), to have this additional behavior:
// crashes with java.lang.NumberFormatException: multiple points
double number2WithError = Double.parseDouble(testInput2.replace(",", "."));
Is there a way I can use NumberFormat to have my required/expected behavior besides writing my own wrapper class that does some additional checks on e.g. multiple decimal separators?
Also I'm aware that the JavaDoc of the used parse(String source) method of NumberFormat says:
Parses text from the beginning of the given string to produce a number. The method may not use the entire text of the given string.
See the {#link #parse(String, ParsePosition)} method for more information on number parsing.
and parse(String source, ParsePosition parsePosition):
Returns a Long if possible (e.g., within the range [Long.MIN_VALUE, Long.MAX_VALUE] and with no decimals), otherwise a Double. If IntegerOnly is set, will stop at a decimal point (or equivalent; e.g., for rational numbers "1 2/3", will stop after the 1). Does not throw an exception; if no object can be parsed, index is unchanged!
This doesn't tell me though why the method behaves this way. What I get from these is that they can parse only parts of the String (what they obviously do here) and probably just start parsing at the beginning (start position) until they find something they can't deal with.
I didn't find an existing question covering this, so if there is already one, please feel free to close this post and please link to it.
NumberFormat.parse(String) is behaving exactly as documented:
Parses text from the beginning of the given string to produce a number. The method may not use the entire text of the given string.
(Emphasis added)
You ask:
Is there a way I can use NumberFormat to have my required/expected behavior besides writing my own wrapper class that does some additional checks on e.g. multiple decimal separators?
You cannot provide a format that will make NumberFormat.parse() throw an exception for input with only an initial substring that can be parsed according to the format. You can, however, use NumberFormat.parse(String, ParsePosition) to determine whether the whole input was parsed, because the parse position argument is used not only to indicate to the method where to start, but also for the method to say where it stopped. That would be a lot better than implementing format-specific extra checks. Example:
ParsePosition position = new ParsePosition(0);
Number result = format.parse(input, position);
if (position.getIndex() != input.length()) {
throw new MyException();
}
Additionally, you write:
This doesn't tell me though why the method behaves this way.
It behaves that way because sometimes parsing the initial portion of the input is exactly what you want to do. You can build stricter parsing on top of more relaxed parsing, as shown, but it's much more difficult to do it the other way around.
I am parsing multiple files in parallel, and from times to times, the format() method will not return the right value.
Number parse = numberFormat.parse(val);
String format = numberFormat.format(parse);
format.equals(parse); //returns false sometimes
At first I thought it was due to the fact that the format method was not thread safe, but it was using a numberformat.clone() for each thread.
I also tried creating a new NumberFormat() for each thread, and also a ThreadLocal<NumberFormat>, with an initial value, and then calling the get() method, all with the same problem.
In the debugger, an evaluation of the expression always return the right value at the breakpoint.
I tried putting multiple lines String format = numberFormat.format(parse);, it turns out that randomly, one or several of the lines return a completely wrong value, and the other return the right one.
I'm 99% sure it's a thread issue, and a concurrent access is made to something, probably the numberFormat itself.
I might not have used the right way to make it thread safe, but in my understanding, using either clone() or new should get rid of that concern.
Any clues as to what is causing the issue, and how to fix it?
EDIT :
Here are two screen shots made with IntelliJ IDEA to showcase the issue :
Extend the NumberFormat class and synchronize the format method:
class SynchronizedNumberFormat extends NumberFormat {
public synchronized String format(Number number) {
return super.format(number);
}
//unimplemented methods...
}
There has never been any guarantee that a NumberFormat's format method will return exactly the same String as what you parsed the number from. In fact, many Strings can yield the same Number value.
First, consider trailing zeroes:
NumberFormat numberFormat = NumberFormat.getInstance();
Number parsed = numberFormat.parse("1.500000000000");
String formatted = numberFormat.format(parsed);
System.out.println(formatted); // prints 1.5
Second, NumberFormat doesn't parse a complete String like the Double.valueOf, Integer.valueOf, etc. It parses as much as it can from the String, and ignores trailing characters. The following are all valid operations that will parse successfully, without throwing a ParseException:
NumberFormat numberFormat = NumberFormat.getInstance();
numberFormat.parse("1.500000000000");
numberFormat.parse("1.5 ");
numberFormat.parse("1.5-----------");
numberFormat.parse("1.5helloworld");
All of the above calls return 1.5.
I have a String: a%sb%sc%s. I need to format b before I format a or c, but I'm not sure how or even if I can specify only to format b while keeping the rest of the String unformatted.
In other words, I'm trying to do this:
String.format(foo, "test");
With the outcome:
a%sbtestc%s
Is it possible to manipulate a String like this or should I just use String.replace instead?
A little more detail. The ultimate String will look something like: aA-PARMbB-PARMcC-PARM and then used to fetch some data. a and c are much more dynamic than b, so I'm trying to format b before hand.
So, again. I'm trying to achieve the following:
String.format(foo, "B-PARM");
With the results:
a%sbB-PARMc%s
Then format the rest:
String.format(formattedFoo, "A-PARM", "C-PARM");
You could do your formatting in steps,
String aString = String.format("something %s something else", "a string");
String bString = String.format("...%s...", "test");
String cString = // ....
String completeString = String.format("a%sb%sc%s", aString, bString, cString);
but again, I have to wonder what is going on, and whether this represents an XY Problem, one that is best solved by a completely different approach. Consider giving us the details of the overall problem that you're trying to solve and perhaps not the code tactics that you're using to try to solve it.
I am currently making an auction program in Java, I am trying to work out deadlines, however my date keeps coming out as (7/04/2013 11:22), is there a way to use String.format to add a leading zero to this date when it is a one digit day?
String timeOne = Server.getDateTime(itemArray.get(1).time).toString()
It causes me a problem later on when I try to sub string it, and it is less than 17 characters long.
Thanks in advance, James.
#Leonard Brünings answer is the right way. And here's why your original code is the wrong way ... even if it worked.
The javadoc for Calendar.toString() says this:
"Return a string representation of this calendar. This method is intended to be used only for debugging purposes, and the format of the returned string may vary between implementations."
Basically you are using toString() for a purpose that the javadoc says you shouldn't. Even if you tweaked the output from toString(), the chances are that your code would be fragile. A change in JVM could break it. A change of locale could break it.
Simply use the SimpleDateFormat
import java.text.SimpleDateFormat;
Calendar timeOne = Server.getDateTime(itemArray.get(1).time)
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm")
System.out.println(sdf.format(timeOne.getTime()))
For various reasons I am trying to set a string to 2000 spaces. Currently I am using:
String s = String.format("%1$-2000s"," ");
This is great for Java 5, however, some of the developers in our department are using 1.4 and this does not work.
I was wondering, are any other ways of achieving the same result? I know I can do things like a for loop adding a space at a time, but I am looking for something simple like the format option.
For those that may be interested in why I need this, it is because we have an XML type on a dataobject that on insert into the DB is null. It then gets updated with the XML string, usually around 2000 characters in size. In Oracle pre-reserving this space can prevent row migration, therefore, increasing performance.
Thanks!
char[] spacesArray = new char[2000];
Arrays.fill(spacesArray, ' ');
String spaces = new String(spacesArray);
the simplest answer: (scroll to see all the codes)
String s = " "; // 2000 spaces
You can use lpad(' ',2000,' ') in the insert statement directly to tell Oracle to create the value you want.
In fact, you can set the field in question to have this as the default, which could prevent you from needing to change it in multiple places (if your code is explicitly sending null as the value for the field, that will override the default).
A StringBuffer and then add a space 2000 times in a loop, and toString() afterwards. I don't think there are any "simpler" ways to do it which doesn't end up doing this anyway under the covers.
If you do this a lot, it would make a good library function.
A random function I found in my personal library:
public static String whiteSpace2(int l) {
if (l==0) return "";
String half=whiteSpace2(l/2);
if ((l&1)!=0) {
return half+" "+half;
} else {
return half+half;
}
}
Not claiming it is the fastest possible way to generate whitespace, but it works :-)
StringUtils.repeat(" ", 2000) (from commons-lang)
However, I'm not sure whether such micro-optimizations should be made with the cost of code that would require a 5 line comment to explain why is this needed. If you do it - be sure to add an extensive comment, otherwise imagine the reaction of those reading your code.
If nothing else works:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 2000; ++i)
sb.append(" ");
String str = new String(sb);
See this other question.
Can I multiply strings in Java to repeat sequences?
Both Apache Commons StringUtils and Google Guava libraries have commands to multiply (repeat) strings.