我有一个这样的数字:
1234567890123
,并希望将其格式化,例如像这样
12 34567 89012 3
或者像这样
1-234 567-890 1 23
我怎样才能做到呢?我试过这个
DecimalFormat decimalFormat = new DecimalFormat("00 00000 00000 0");
System.out.println(decimalFormat.format(1234567890123L));
但是这行不通。
我需要一种方法来指定一个可以包含任何分隔符的模式。
import java.text.ParseException;
import javax.swing.text.MaskFormatter;
import org.junit.jupiter.api.Test;
public class FormatTest {
@Test
void testNumberFormat() throws ParseException {
final String format = "#-### ###-### # ##";
final String number = "1234567890123";
MaskFormatter maskFormatter = new MaskFormatter(format);
maskFormatter.setValueContainsLiteralCharacters(false);
System.out.println(maskFormatter.valueToString(number));
}
}
对于DecimalFormatter
和NumberFormatter
,这是不可能的。但是您可以使用String
和正则表达式的技巧:
Long.toString(number)
.replaceAll("(\d{2})(\d{5})(\d{5})(\d)", "$1 $2 $3 $4");
如果你的格式是动态的,你可以这样做:
@Test
void simon() {
final var input = 1234567890123L;
assertEquals("12 34567 89012 3", formatMyNumber(input, "{2} {5} {5} {1}"));
assertEquals("12-34567-89012-3", formatMyNumber(input, "{2}-{5}-{5}-{1}"));
assertEquals("12_34567_89012_3", formatMyNumber(input, "{2}_{5}_{5}_{1}"));
assertEquals("1 23456 7", formatMyNumber(1234567, "{1} {5} {1}"));
assertEquals("1 2345 6", formatMyNumber(123456, "{1} {4} {1}"));
assertEquals("123.45.6", formatMyNumber(123456, "{3}.{2}.{1}"));
}
private String formatMyNumber(final long number, final String format) {
return Long.toString(number).replaceAll(createRegEx(format), createReplacement(format));
}
private String createRegEx(final String format) {
final var separator = getSeparator(format);
return format.replaceAll("\{", "(\\d{")
.replaceAll("}" + Pattern.quote(separator), "}\)")
.replaceAll("}$", "}\)"); // could be integrated in above regex
}
private String getSeparator(final String format) {
final var begin = format.indexOf("}");
final var end = format.indexOf("{", begin);
return format.substring(begin + 1, end);
}
private String createReplacement(final String format) {
final var separator = getSeparator(format);
var replacement = format.replaceAll("^\{\d", "\$X")
.replaceAll("}" + Pattern.quote(separator) + "\{\d", separator + "\$X")
.replaceAll("}$", "");
var counter = 1;
while (replacement.contains("X")) {
replacement = replacement.replaceFirst("X", Integer.toString(counter++));
}
return replacement;
}
这不是我最好的作品,但可以使用动态格式字符串。
这里有一些东西可以让你开始。请随意修改代码以满足您的需要。
public class ArbitraryFormat {
public static void main(String[] args) {
ArbitraryFormat arbitraryFormat = new ArbitraryFormat("00 00000 00000 0");
System.out.println(arbitraryFormat.format(1234567890123L));
System.out.println(arbitraryFormat.format(123));
}
private int zeroCount;
private String formatter;
public ArbitraryFormat(String formatter) {
this.formatter = formatter;
this.zeroCount = countZeros(formatter);
}
public String format(long value) {
String tempFormatter = "%" + zeroCount + "s";
String temp = String.format(tempFormatter, value);
StringBuilder builder = new StringBuilder();
int tempIndex = 0;
for (int index = 0; index < formatter.length(); index++) {
if (formatter.charAt(index) == '0') {
builder.append(temp.charAt(tempIndex++));
} else {
builder.append(formatter.charAt(index));
}
}
return builder.toString();
}
private int countZeros(String formatter) {
int count = 0;
int index = 0;
while (index < formatter.length()) {
int pos = formatter.indexOf('0', index);
if (pos >= 0) {
count++;
index = pos + 1;
} else {
index = formatter.length();
}
}
return count;
}
}
你可以像这样定义你自己的格式化器。
public class MyFormat extends NumberFormat {
final String format;
public MyFormat(String format) {
this.format = format;
}
@Override
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
throw new UnsupportedOperationException();
}
@Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
toAppendTo.append(number);
for (int i = toAppendTo.length() - 1, j = format.length() - 1; i >= 0 && j >= 0; --i, --j) {
char fch = format.charAt(j);
if (fch != '*') {
toAppendTo.insert(i + 1, fch);
--j;
}
}
return toAppendTo;
}
@Override
public java.lang.Number parse(String source, ParsePosition parsePosition) {
throw new UnsupportedOperationException();
}
}
和
public static void main(String[] args) throws ParseException {
long number = 1234567890123L;
MyFormat mf1 = new MyFormat("* ***** ***** *");
MyFormat mf2 = new MyFormat("*-*** ***-*** * **");
System.out.println(mf1.format(number));
System.out.println(mf2.format(number));
}
输出:
12 34567 89012 3
1-234 567-890 1 23
多亏了@McPringle,我终于实现了这个解决方案:
public class MaskFormatter {
private char[] separators;
public String formatNumber(Number number, String pattern) {
if (number == null) {
return "";
} else {
separators = pattern.replace("0", "").toCharArray();
String string = number.toString();
String regex = createRegex(pattern);
String replacement = createReplacement(pattern);
return string.replaceAll(regex, replacement);
}
}
private String createRegex(String pattern) {
String[] parts = pattern.split("[" + createPatternFromSeparators() + "]");
StringBuilder sb = new StringBuilder();
for (String part : parts) {
sb.append("(\d{").append(part.length()).append("})");
}
return sb.toString();
}
private String createReplacement(String pattern) {
String[] parts = pattern.split("[" + createPatternFromSeparators() + "]");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
if (i > 0) {
char separator = separators[i - 1];
sb.append(separator);
}
sb.append("$").append(i + 1);
}
return sb.toString();
}
private String createPatternFromSeparators() {
Set<String> set = new HashSet<>();
for (char separator : separators) {
set.add(String.valueOf(separator));
}
return String.join("", set);
}
}
您也可以使用String.replaceAll()
。就像下面的例子。
long value = 1234567890123L;
String str = String.valueOf(value);
//12 34567 89012 3
String str1 = str.replaceAll("^(.{2})(.{5})(.{5})(.{1})$", "$1 $2 $3 $4");
System.out.println(str1); //Prints: 12 34567 89012 3
//1-234 567-890 1 23
String str2 = str.replaceAll("^(.{1})(.{3})(.{3})(.{3})(.{1})(.{2})$", "$1-$2 $3-$4 $5 $6");
System.out.println(str2); //Prints: 1-234 567-890 1 23