masking a creditcard number in java
Here you go. Clean and reusable:
/**
* Applies the specified mask to the card number.
*
* @param cardNumber The card number in plain format
* @param mask The number mask pattern. Use # to include a digit from the
* card number at that position, use x to skip the digit at that position
*
* @return The masked card number
*/
public static String maskCardNumber(String cardNumber, String mask) {
// format the number
int index = 0;
StringBuilder maskedNumber = new StringBuilder();
for (int i = 0; i < mask.length(); i++) {
char c = mask.charAt(i);
if (c == '#') {
maskedNumber.append(cardNumber.charAt(index));
index++;
} else if (c == 'x') {
maskedNumber.append(c);
index++;
} else {
maskedNumber.append(c);
}
}
// return the masked number
return maskedNumber.toString();
}
Sample Calls:
System.out.println(maskCardNumber("1234123412341234", "xxxx-xxxx-xxxx-####"));
> xxxx-xxxx-xxxx-1234
System.out.println(maskCardNumber("1234123412341234", "##xx-xxxx-xxxx-xx##"));
> 12xx-xxxx-xxxx-xx34
Good luck.
Using Apache StringUtils...
String ccNumber = "123232323767";
StringUtils.overlay(ccNumber, StringUtils.repeat("X", ccNumber.length()-4), 0, ccNumber.length()-4);
Here's a slightly cleaner implementation based on StringUtils, though I am not sure how it would perform in comparison to your implementations. At any rate, the 'premature optimization' comments remain very valid.
public static String maskNumber(final String creditCardNumber) {
final String s = creditCardNumber.replaceAll("\\D", "");
final int start = 4;
final int end = s.length() - 4;
final String overlay = StringUtils.repeat(MASK_CHAR, end - start);
return StringUtils.overlay(s, overlay, start, end);
}