繁体   English   中英

在java中屏蔽信用卡号

[英]masking a creditcard number in java

我尝试使用字符“X”来掩盖信用卡号码字符串中的字符。我编写了两个函数,如下所示。第二个函数使用commons.lang.StringUtils类。我试图找出两种情况下所需的时间

public static String maskCCNumber(String ccnum){
        long starttime = System.currentTimeMillis();
        int total = ccnum.length();
        int startlen=4,endlen = 4;
        int masklen = total-(startlen + endlen) ;
        StringBuffer maskedbuf = new StringBuffer(ccnum.substring(0,startlen));
        for(int i=0;i<masklen;i++) {
            maskedbuf.append('X');
        }
        maskedbuf.append(ccnum.substring(startlen+masklen, total));
        String masked = maskedbuf.toString();
        long endtime = System.currentTimeMillis();
        System.out.println("maskCCNumber:="+masked+" of :"+masked.length()+" size");
        System.out.println("using StringBuffer="+ (endtime-starttime)+" millis");
        return masked;
    }

    public static String maskCCNumberCommons(String ccnum){
        long starttime = System.currentTimeMillis();
        int total = ccnum.length();
        int startlen=4,endlen = 4;
        int masklen = total-(startlen + endlen) ;
        String start = ccnum.substring(0,startlen);
        String end = ccnum.substring(startlen+masklen, total);
        String padded = StringUtils.rightPad(start, startlen+masklen,'X'); 
        String masked = padded.concat(end);
        long endtime = System.currentTimeMillis();
        System.out.println("maskCCNumber:="+masked+" of :"+masked.length()+" size");
        System.out.println("using Stringutils="+(endtime-starttime)+" millis");
        return masked;
    }

public static void ccNumberMaskingDemo() {
   String mcard1="5555555555554444";
   maskCCNumber(mcard1);
   maskCCNumberCommons(mcard1);
}

当我运行这个时,我得到了这个结果

maskCCNumber:=5555XXXXXXXX4444 of :16 size
using StringBuffer=0 millis
maskCCNumber:=5555XXXXXXXX4444 of :16 size
using Stringutils=25 millis

我不明白为什么 commons.StringUtils 比第一个函数中的 for loop+StringBuffer 花费更多的时间。显然我正在使用 api,错误的方式..

在这种情况下,有人可以建议如何正确使用这个 api 吗?

干得好。 清洁和可重复使用:

/**
 * 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();
}

示例调用:

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

祝你好运。

使用 Apache StringUtils...

String ccNumber = "123232323767"; 

StringUtils.overlay(ccNumber, StringUtils.repeat("X", ccNumber.length()-4), 0, ccNumber.length()-4);

这是一个基于 StringUtils 的稍微干净的实现,尽管我不确定与您的实现相比它会如何执行。 无论如何,“过早的优化”评论仍然非常有效。

    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);
}

首先,如果您测量这样一个短时间运行的代码,由于您的 CPU/库/任何提供的最小时间分辨率(这意味着您通常会看到 0ms 或相同的小值),您通常不会得到准确的结果。超过)。

其次,更重要的是,不要优化这个! “过早的优化是万恶之源” ,如果您只有几毫秒的时间想要优化,那么您的努力就完全浪费了。 在远程考虑优化这种简单的屏蔽方法之前,您必须屏蔽数百万张信用卡。

我知道这不是答案,但您可以使用正则表达式并一步解决此问题

String replaced = originalCreditCardNo.replaceAll("\\b(\\d{4})(\\d{8})(\\d{4})", "$1XXXXXXXX$3");

解释:

  • \b边界有助于检查我们是否是数字的开头(还有其他方法可以做到这一点,但在这里就可以了)。
  • (\d{4})将四位数字捕获到第 1 组和第 3 组
  • (\d{8})将八位数字捕获到第 2 组
  • 在替换中, $1$3包含第 1 组和第 3 组匹配的内容

下面的代码将屏蔽 75% 的字符串。

public static String mask(String input) {

    int length = input.length() - input.length()/4;
    String s = input.substring(0, length);
    String res = s.replaceAll("[A-Za-z0-9]", "X") + input.substring(length);


    return res;
}

String utils 可能会复制字符串几次。 例如当你运行 padded.concat(end); jvm分配两个concat字符串大小的新字符串并复制它们。 如果您使用 StringBuffer ,您将保存所有这些副本,因为缓冲区已经分配了位置,并且连接的字符串刚刚复制到那里。 对我来说,StringBuffer 更快是有道理的,尽管测量的时间似乎比我预期的要大。

import java.util.Scanner;
class StringTest{
    public static void main(String ar[]){
        Scanner s=new Scanner(System.in);

        System.out.println("enter account number");
        String name=s.next();
        char a[]=new char[name.length()];
        for(int i=0;i<name.length();i++){
            a[i]=name.charAt(i);
        }
        for(int i=1;i<name.length()-3;i++){
            a[i]='*';
        }

        System.out.println("your account number");
        for(int i=0;i<name.length();i++){
            System.out.print(a[i]);
        }
    }
}

很可能,这是从apache-commons.jar文件加载StringUtils的时间。 不是真正的执行时间。

要计算真正的执行时间,请尝试运行多次,看看第二次会有多少毫秒。 第 3 到第 100 将采取。

无论如何,正如弗兰克所说,不建议优化到这个级别。

虽然可读性较差,但您可以这样做

final char[] ca = in.toCharArray();
Arrays.fill(ca, left, str.length - right, 'X');
return new String(ca)

在我的机器上使用 Google Caliper 将产生大约 20-25 ns,而使用 StringBuilder 或 StringUtils.overlay + 重复方法则超过 100ns。

import static org.apache.commons.lang3.StringUtils.overlay;
import static org.apache.commons.lang3.StringUtils.repeat;

import java.util.Arrays;

import org.apache.commons.lang3.StringUtils;

import com.google.caliper.Param;
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class ArrayCopyVsStringBuild extends SimpleBenchmark {

    public static void main(final String[] args) throws Exception {
        Runner.main(ArrayCopyVsStringBuild.class, args);
    }

    @Param({ "1234567890123456", "1234567890" })
    private String input;

    @Param({ "0", "4" })
    private int left;

    @Param({ "0", "4" })
    private int right;

    public void timeArray(final int reps) {
        for (int i = 0; i < reps; i++) {
            final char[] masked = input.toCharArray();
            Arrays.fill(masked, left, masked.length - right, 'X');
            final String x = new String(masked);
            x.toString();
        }
    }

    public void timeStringBuilder(final int reps) {
        for (int i = 0; i < reps; i++) {
            final StringBuilder b = new StringBuilder(input.length());
            b.append(input.substring(0, left));
            for (int z = 0; z < input.length() - left - right; ++z) {
                b.append('X');
            }
            b.append(input.substring(input.length() - right));
            final String x = b.toString();
            x.toString();
        }
    }

    public void timeStringUtils(final int reps) {
        for (int i = 0; i < reps; i++) {
            final StringBuilder b = new StringBuilder(input.length());
            b.append(input.substring(0, left));
            b.append(repeat('x', input.length() - left - right));
            b.append(input.substring(input.length() - right));
            final String x = b.toString();
            x.toString();
        }
    }

    public void timeStringUtilsOverlay(final int reps) {
        for (int i = 0; i < reps; i++) {
            final int maskLength = input.length() - left - right;
            final String x = overlay(input, repeat('x', maskLength), left,
                    maskLength + left);
            x.toString();
        }
    }
}
public class MaskCreditCard {

static void creditcard(String cc) {

    StringBuffer s = new StringBuffer();

    if (cc.length() <= 4) {
        System.out.println(cc);
    } else if (cc.length() > 16) {
        System.out.println("Give a valid 16 digit CC number");
    }

    else {
        for (int i = cc.length() - 4; i > 0; i--) {
            s.append("#");
        }
        System.out.println(s + "" + cc.substring(cc.length() - 4));
    }
}

public static void main(String[] args) {

    creditcard("11111111111111111111111111111111");

}

}
String existingCCNmbr = "4114360123456785";
    int i = 0;
    StringBuffer temp = new StringBuffer();
    while(i < (existingCCNmbr .length())){
        if(i > existingCCNmbr .length() -5){
            temp.append(existingCCNmbr.charAt(i));
        } else {
            temp.append("X");
        }
        i++;
    }
       System.out.println(temp);
       }

输出:XXXXXXXXXXXX6785

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM