7

i will like to know how do i mask any number of string characters except the last 4 strings. I want to masked all strings using "X"

For example

Number:"S1234567B"

Result

Number :"XXXXX567B

Thank you guys

BinQuan
  • 85
  • 2
  • 2
  • 6

5 Answers5

21

Solution 1

You can do it with a regular expression.
This is the shortest solution.

static String mask(String input) {
    return input.replaceAll(".(?=.{4})", "X");
}

The regex matches any single character (.) that is followed (zero-width positive lookahead) by at least 4 characters ((?=.{4})). Replace each such single character with an X.


Solution 2

You can do it by getting a char[]1, updating it, and building a new string.
This is the fastest solution, and uses the least amount of memory.

static String mask(String input) {
    if (input.length() <= 4)
        return input; // Nothing to mask
    char[] buf = input.toCharArray();
    Arrays.fill(buf, 0, buf.length - 4, 'X');
    return new String(buf);
}

1) Better than using a StringBuilder.


Solution 3

You can do it using the repeat​(int count) method that was added to String in Java 11.
This is likely the easiest solution to understand.

static String mask(String input) {
    int maskLen = input.length() - 4;
    if (maskLen <= 0)
        return input; // Nothing to mask
    return "X".repeat(maskLen) + input.substring(maskLen);
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
1

Kotlin extension which will take care of the number of stars that you want to set and also number of digits for ex: you have this string to be masked: "12345678912345" and want to be ****2345 then you will have:

fun String.maskStringWithStars(numberOfStars: Int, numberOfDigitsToBeShown: Int): String {
var stars = ""
for (i in 1..numberOfStars) {
    stars += "*"
}
return if (this.length > numberOfDigitsToBeShown) {
    val lastDigits = this.takeLast(numberOfDigitsToBeShown)
    "$stars$lastDigits"
} else {
    stars
}

}

Usage:

   companion object{
    const val DEFAULT_NUMBER_OF_STARS = 4
    const val DEFAULT_NUMBER_OF_DIGITS_TO_BE_SHOWN = 4
    
    }
   yourString.maskStringWithStars(DEFAULT_NUMBER_OF_STARS,DEFAULT_NUMBER_OF_DIGITS_TO_BE_SHOWN)
Liridon Sadiku
  • 309
  • 3
  • 7
0

You can use a StringBuilder.

StringBuilder sb = new StringBuilder("S1234567B");
for (int i = 0 ; i < sb.length() - 4 ; i++) { // note the upper limit of the for loop
    // sets every character to X until the fourth to last character
    sb.setCharAt(i, 'X');
}
String result = sb.toString();
Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

You can do it with the help of StringBuilder in java as follows,

String value = "S1234567B";
String formattedString = new StringBuilder(value)
    .replace(0, value.length() - 4, new String(new char[value.length() - 4]).replace("\0", "x")).toString();
System.out.println(formattedString);
823
  • 63
  • 8
  • `value = "7B"` causes `NegativeArraySizeException: -2` --- This is also the most convoluted solution presented so far. – Andreas Oct 13 '19 at 08:52
  • *"I assume the values lengths are more than 4"* You know what they say about assumptions. Besides, [defensive programming](https://en.wikipedia.org/wiki/Defensive_programming) practices to handle unexpected cases too, so unless you explicitly want it to the fail for inputs less than 4 in length, you should handle it. – Andreas Oct 13 '19 at 09:30
  • *"whats the complexity of this solution?"* Big-O complexity is _O(n)_, same as all the other solutions, but why do you ask? I said *convoluted*, as in more difficult to follow the logic. I didn't say *complex*. And even though they are all _O(n)_ still doesn't mean they all perform the same, so again I don't understand why you ask about *complexity*. – Andreas Oct 13 '19 at 09:43
0

My class to mask simple String

class MaskFormatter(private val pattern: String, private val splitter: Char? = null) {

    fun format(text: String): String {
        val patternArr = pattern.toCharArray()
        val textArr = text.toCharArray()
        var textI = 0
        for (patternI in patternArr.indices) {
            if (patternArr[patternI] == splitter) {
                continue
            }
            if (patternArr[patternI] == 'A' && textI < textArr.size) {
                patternArr[patternI] = textArr[textI]
            }
            textI++
        }
        return String(patternArr)
    }
}

Example use

MaskFormatter("XXXXXAAAA").format("S1234567B") // XXXXX567B
MaskFormatter("XX.XXX.AAAA", '.').format("S1234567B") // XX.XXX.567B
MaskFormatter("**.***.AAAA", '.').format("S1234567B") // **.***.567B
MaskFormatter("AA-AAA-AAAA",'-').format("123456789") // 12-345-6789
Linh
  • 57,942
  • 23
  • 262
  • 279