精华内容
下载资源
问答
  • C#中用Graphics输出指定字符间距的字符串
  • 一般用条码打印软件制作条形码,下面的条形码数据间距是自动生成的,而在条码打印软件制作的条形码是可以根据自己的需要手动设置这些字符间距,接下来就一起看看如何自定义条码字符间距。 在条码打印软件中制作一个...

    条形码有两部分组成,上面是黑白条图案,用于扫描设备的识别,下面是条形码数据,方便在没有扫描设备的情况下可以手动去搜索相关的信息。一般用条码打印软件制作条形码,下面的条形码数据间距是自动生成的,而在条码打印软件制作的条形码是可以根据自己的需要手动设置这些字符间距,接下来就一起看看如何自定义条码字符间距。
    在条码打印软件中制作一个条形码,在条码属性中可以修改条码数据。
    在这里插入图片描述
    在条形码的“图形属性”-“文字”选项中可以直接修改字间距,根据自己的需要手动设置字间距。
    在这里插入图片描述
    当然还可以把条码数据选择两端对齐,这样条形码数据就会根据条形码的宽度平均分散。这个时候就要注意,选择两端对齐之后,再设置字间距就是无效的。
    在这里插入图片描述
    在条码打印软件中还有另一种方法也可以修改条形码字符间距,是通过格式化的方式来实现,还是在条形码属性的“文字”选项中,设置格式化,条码数据有多少位就输入多少个输入英文的问号“?”,然后你就可以在问号之间加空格,在哪加空格,加多少空格,都可以根据自己的需要设置。(也可以加其他自己需要的字符,不影响条形码的识别)
    在这里插入图片描述
    以上就是在条码打印软件中自定义设置条形码下面的字符间距的几种方法,条码打印软件不论是条形码的字符间距设置还是条形码的数据输入,或者条形码的类型选择都是非常方便灵活的,感兴趣的可以下载体验一下。

    展开全文
  • 2.1.17 设置字符间距

    2019-11-10 19:53:41
    2.1.17 设置字符间距 示例代码: package test.create.c02; import vita.ofd.layout.OfdDocument; import vita.ofd.layout.contants.AlignmentType; import vita.ofd.layout.element.Paragraph; import vita.ofd....

    2.1.17 设置字符间距

    示例代码:

    package test.create.c02;
    
    import vita.ofd.layout.OfdDocument;
    import vita.ofd.layout.contants.AlignmentType;
    import vita.ofd.layout.element.Paragraph;
    import vita.ofd.layout.element.paragraph.Text;
    
    /**
     * 展示如何设置文字间距, 设置的值单位是PT(磅)
     * */
    public class C0217SetFontWidth {
    
    	public static void main(String[] args) throws Throwable {
    		C0217SetFontWidth o = new C0217SetFontWidth();
    		o.done();
    	}
    
    	private void done() throws Throwable {
    		String clzName = this.getClass().getSimpleName();
    		System.out.println(clzName + " begin");
    		
    		String s = "中国 China 自主可控 vita";
    		OfdDocument doc = new OfdDocument();
    		Paragraph p = new Paragraph();
    		Text text = new Text(s);
    		/*
    		 * 设置文字间距, 设置的值单位是PT(磅)
    		 * */
    		text.setCharacterSpacing(12);
    		p.add(text);
    		p.setAlignment(AlignmentType.BOTH_ENDS);
    		doc.add(p);
    		
    		doc.save(clzName + ".ofd");
    		System.out.println(clzName + " end");
    	}
    }
    
    

    显示效果如下:
    在这里插入图片描述

    iOFD是用于生成OFD文档的Java类库。iOFD确保开发人员无需了解OFD文档格式规范的情况下,通过添加段落、图标、图片、表格、页头、页尾、页面、页码、水印和其他高级对象,结合直观的构建元素,很容易地通过编程的方式来创建一个OFD文档。并且创建OFD文档所需的代码量更少,更加容易阅读和理解,提升代码可维护性,降低开发成本。
    iOFD提供基于SM2国产密码算法的电子签章功能,满足国家安全电子签章密码技术规范相关要求。
    iOFD的安装非常方便,只需要在系统的CLASSPATH中加入相关jar包,在程序中就可以使用iOFD类库了。
    iOFD官方网站:iofd.dms360.cn
    EMail:dms_support@126.com
    QQ联系方式:3326656468

    展开全文
  • 给定一个非空字符串str和一个整数k,请重新排列该字符串,以使相同字符之间的距离至少为k。 所有输入字符串均以小写字母给出。...Java解决方案 public String rearrangeString(String str, int k) { i...

    给定一个非空字符串str和一个整数k,请重新排列该字符串,以使相同字符之间的距离至少为k。
    所有输入字符串均以小写字母给出。如果无法重新排列字符串,则返回一个空字符串“”。
    例:
    str =“ aabbcc”,k = 3
    结果:“ abcabc”
    相同字母之间的距离至少为3。
    Java解决方案
    public String rearrangeString(String str, int k) {
    if(k==0)
    return str;

    //initialize the counter for each character
    final HashMap<Character, Integer> map = new HashMap<Character, Integer>();
    for(int i=0; i<str.length(); i++){
        char c = str.charAt(i);
        if(map.containsKey(c)){
            map.put(c, map.get(c)+1);
        }else{
            map.put(c, 1);
        }
    }
    
    //sort the chars by frequency
    PriorityQueue<Character> queue = new PriorityQueue<Character>(new Comparator<Character>(){
        public int compare(Character c1, Character c2){
            if(map.get(c2).intValue()!=map.get(c1).intValue()){
                return map.get(c2)-map.get(c1);
            }else{
                return c1.compareTo(c2);
            }
        }
    });
    
    
    for(char c: map.keySet())
        queue.offer(c);
    
    StringBuilder sb = new StringBuilder();
    
    int len = str.length();
    
    while(!queue.isEmpty()){
    
        int cnt = Math.min(k, len);
        ArrayList<Character> temp = new ArrayList<Character>();
    
        for(int i=0; i<cnt; i++){
            if(queue.isEmpty())
                return "";
    
            char c = queue.poll();
            sb.append(String.valueOf(c));
    
            map.put(c, map.get(c)-1);
    
            if(map.get(c)>0){
                temp.add(c);
            }
    
            len--;
        }
    
        for(char c: temp)
            queue.offer(c);
    }
    
    return sb.toString();}
    

    最后,开发这么多年我也总结了一套学习Java的资料与面试题,如果你在技术上面想提升自己的话,可以关注我,私信发送领取资料或者在评论区留下自己的联系方式,有时间记得帮我点下转发让跟多的人看到哦。在这里插入图片描述

    展开全文
  • Java实现字符验证码、运算验证码

    千次阅读 2019-08-21 11:13:36
    Java中很轻松可以实现验证码功能,在原生AWT图形化工具包中写一点简单的逻辑就能轻松完成验证码功能。 本文,同时将google的kaptcha验证码一同讲解。 项目地址:https://gitee.com/gester/captcha.git 原创不易!...

    Java中很轻松可以实现验证码功能,在原生AWT图形化工具包中写一点简单的逻辑就能轻松完成验证码功能。
    本文,同时将google的kaptcha验证码一同讲解。

    项目地址:https://gitee.com/gester/captcha.git

    同时,推一下Java滑动验证码的原理与实现文章。文章地址:https://blog.csdn.net/YTenderness/article/details/99969355

    原创不易!如果有帮到您,请给作者小星星鼓励一下

    功能

    1. 字符验证码
      • AWT实现字符验证码
      • kaptcha实现字符验证码
    2. 运算验证码
      • AWT实现运算验证码
      • kaptcha实现运算验证码
    3. 滑动验证码(扩展)
      由于代码量较大,功能关联性不强。一篇文章不够清楚说明,将在另外一篇文章讲解。

    相关依赖

    		<dependency>
    			<groupId>com.github.penggle</groupId>
    			<artifactId>kaptcha</artifactId>
    			<version>2.3.2</version>
    		</dependency>
    

    ####一. AWT实现验证码
    字符验证码:

     /**
         * 生成字符验证码
         * @return 字符验证码
         */
        public static Map<String, Object> generatorCharVerificationCode() {
            //  验证码图片边框宽度
            final int WIDTH = 150;
            //  验证码图片边框高度
            final int HEIGHT = 50;
            //  验证码字符长度
            int CHAR_LENGTH = 6;
            //  验证码字体高度
            int FONT_HEIGHT = HEIGHT - 12;
            //  验证码干扰线条数
            int INTERFERENCE_LINE = 4;
            //  生成验证码所需字符
            char[] charSequence = {
                    'A', 'B', 'C', 'D', 'E', 'F',
                    'G', 'H', 'I', 'J', 'K', 'L',
                    'M', 'N', 'O', 'P', 'Q', 'R',
                    'S', 'T', 'U', 'V', 'W', 'X',
                    'Y', 'Z', '0', '1', '2', '3',
                    '4', '5', '6', '7', '8', '9'
            };
            Map<String, Object> verificationCodeMap = null;
    
            //  生成透明rgb图片
            BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
            Graphics graphics = bufferedImage.getGraphics();
            //  备份原始画笔颜色
            Color color = graphics.getColor();
            graphics.setColor(Color.BLACK);
            //  图片填充黑色
            graphics.fillRect(0, 0, WIDTH, HEIGHT);
    
            graphics.setColor(Color.WHITE);
            //  图片填充白色;组成黑色边框的白色图片
            graphics.fillRect(1, 1, WIDTH - 2, HEIGHT - 2);
    
            int newFontHeight = CHAR_LENGTH > 4 ? FONT_HEIGHT * 4 / CHAR_LENGTH : FONT_HEIGHT;
    
            //  设置画笔字体
            Font font = new Font("微软雅黑", Font.PLAIN, newFontHeight);
            graphics.setFont(font);
            //  根据系统时间创建随机数对象
            Random random = new Random(System.currentTimeMillis());
            int r = 0;
            int g = 0;
            int b = 0;
            //  验证码字符串
            StringBuilder verificationCode = new StringBuilder();
            for (int i = 0; i < CHAR_LENGTH; i++) {
                char ch = charSequence[random.nextInt(charSequence.length)];
                //   随机生成rgb颜色值,并设置画笔颜色
                r = random.nextInt(255);
                g = random.nextInt(255);
                b = random.nextInt(255);
                graphics.setColor(new Color(r, g, b));
                //  根据画笔颜色绘制字符
                graphics.drawString(String.valueOf(ch), i * (newFontHeight), FONT_HEIGHT);
                verificationCode.append(ch);
            }
    
            //  绘制干扰线
            int x1, y1, x2, y2;
            for (int i = 0; i < INTERFERENCE_LINE; i++) {
                //   随机生成rgb颜色值,并设置画笔颜色
                r = random.nextInt(255);
                g = random.nextInt(255);
                b = random.nextInt(255);
                graphics.setColor(new Color(r, g, b));
                x1 = random.nextInt(WIDTH);
                y1 = random.nextInt(HEIGHT);
                x2 = random.nextInt(WIDTH);
                y2 = random.nextInt(HEIGHT);
                //  绘制线条
                graphics.drawLine(x1, y1, x2, y2);
            }
    
            //  恢复画笔颜色
            graphics.setColor(color);
    
            verificationCodeMap = new HashMap<String, Object>();
            verificationCodeMap.put("verificationCodeImage", bufferedImage);
            verificationCodeMap.put("verificationCode", verificationCode);
            return verificationCodeMap;
    
        }
    
            public static void main(String[] args) throws IOException {
                Map<String, Object> charMap = generatorCharVerificationCode();
                BufferedImage bufferedImage1 = (BufferedImage) charMap.get("verificationCodeImage");
    
                OutputStream outputStream1 = new FileOutputStream("C:/Users/Administrator/Desktop/charVerificationCodeImage.png");
                ImageIO.write(bufferedImage1, "png", outputStream1);
                System.out.println("验证码: " + charMap.get("verificationCode"));
                outputStream1.flush();
                outputStream1.close();
            }
    

    预览图
    charVerificationCodeImage.png

    运算验证码:

    
        static StringBuilder result = new StringBuilder();  // 运算验证码结果
        /**
         * 生成运算验证码
         * @return  运算验证码
         */
        public static Map<String, Object> generatorOperationVerificationCode() {
            //  验证码图片边框宽度
            final int WIDTH = 185;
            //  验证码图片边框高度
            final int HEIGHT = 50;
            //  验证码字体高度
            int FONT_HEIGHT = HEIGHT - 12;
            //  验证码干扰线条数
            int INTERFERENCE_LINE = 4;
    
            Map<String, Object> verificationCodeMap = null;
    
            //  生成透明rgb图片
            BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
            Graphics graphics = bufferedImage.getGraphics();
            //  备份原始画笔颜色
            Color color = graphics.getColor();
            graphics.setColor(Color.BLACK);
            //  图片填充黑色
            graphics.fillRect(0, 0, WIDTH, HEIGHT);
    
            graphics.setColor(Color.WHITE);
            //  图片填充白色;组成黑色边框的白色图片
            graphics.fillRect(1, 1, WIDTH - 2, HEIGHT - 2);
    
            //  验证码字符串
            String text = getText();
            //  运算表达式
            String operationExpression = text.substring(0, text.lastIndexOf("@") - 1);
            //  计算结果
            String result = text.substring(text.lastIndexOf("@") + 1, text.length());
    
            int newFontHeight = operationExpression.length() > 4 ? FONT_HEIGHT * 4 / operationExpression.length() : FONT_HEIGHT;
    
            //  设置画笔字体
            Font font = new Font("微软雅黑", Font.PLAIN, FONT_HEIGHT);
            graphics.setFont(font);
            //  根据系统时间创建随机数对象
            Random random = new Random(System.currentTimeMillis());
            int r = 0;
            int g = 0;
            int b = 0;
    
            //   随机生成rgb颜色值,并设置画笔颜色
            r = random.nextInt(255);
            g = random.nextInt(255);
            b = random.nextInt(255);
            graphics.setColor(new Color(r, g, b));
            //  根据画笔颜色绘制字符
            graphics.drawString(operationExpression, 5, FONT_HEIGHT);
    
            //  绘制干扰线
            int x1, y1, x2, y2;
            for (int i = 0; i < INTERFERENCE_LINE; i++) {
                //   随机生成rgb颜色值,并设置画笔颜色
                r = random.nextInt(255);
                g = random.nextInt(255);
                b = random.nextInt(255);
                graphics.setColor(new Color(r, g, b));
                x1 = random.nextInt(WIDTH);
                y1 = random.nextInt(HEIGHT);
                x2 = random.nextInt(WIDTH);
                y2 = random.nextInt(HEIGHT);
                //  绘制线条
                graphics.drawLine(x1, y1, x2, y2);
            }
    
            //  恢复画笔颜色
            graphics.setColor(color);
    
            verificationCodeMap = new HashMap<String, Object>();
            verificationCodeMap.put("verificationCodeImage", bufferedImage);
            verificationCodeMap.put("verificationCode", result);
            return verificationCodeMap;
    
        }
    
        /**
         * 获取运算验证码
         * @return 运算验证码
         */
        public static String getText() {
            Random random = new Random(System.currentTimeMillis());
            int x = random.nextInt(51);
            int y = random.nextInt(51);
            int operationalRules = random.nextInt(4);
    
            switch (operationalRules) {
                case 0:
                    add(x, y);
                    break;
                case 1:
                    subtract(x, y);
                    break;
                case 2:
                    multiply(x, y);
                    break;
                case 3:
                    divide(x, y);
                    break;
            }
            return result.toString();
        }
    
        /**
         * 加法运算
         * @param x 变量x
         * @param y 变量y
         */
        private static void add(int x, int y) {
            result.append(x);
            result.append(" + ");
            result.append(y);
            result.append(" = ?@");
            result.append(x + y);
        }
    
        /**
         * 减法运算
         * @param x 变量x
         * @param y 变量y
         */
        private static void subtract(int x, int y) {
            int max = Math.max(x, y);
            int min = Math.min(x, y);
            result.append(max);
            result.append(" - ");
            result.append(min);
            result.append(" = ?@");
            result.append(max - min);
        }
    
        /**
         * 乘法运算
         * @param x 变量x
         * @param y 变量y
         */
        private static void multiply(int x, int y) {
            int value = x * y;
            result.append(x);
            result.append(value > 100 ? " + " : " * ");
            result.append(y);
            result.append(" = ?@");
            result.append(value > 100 ? x + y : x * y);
        }
    
        /**
         * 出发运算
         * @param x 变量x
         * @param y 变量y
         */
        private static void divide(int x, int y) {
            int max = Math.max(x, y);
            int min = Math.min(x, y);
            if (min == 0) {
                multiply(max, min);
            } else if (max % min == 0) {
                result.append(max);
                result.append(" / ");
                result.append(min);
                result.append(" = ?@");
                result.append(max / min);
            } else {
                result.append(max);
                result.append(" % ");
                result.append(min);
                result.append(" = ?@");
                result.append(max % min);
            }
        }
    
    
        public static void main(String[] args) throws IOException {
            Map<String, Object> operationMap = generatorOperationVerificationCode();
            BufferedImage bufferedImage2 = (BufferedImage) operationMap.get("verificationCodeImage");
    
            OutputStream outputStream2 = new FileOutputStream("C:/Users/Administrator/Desktop/operationVerificationCodeImage.png");
            ImageIO.write(bufferedImage2, "png", outputStream2);
            System.out.println("验证码: " + operationMap.get("verificationCode"));
            outputStream2.flush();
            outputStream2.close();
        }
    
    

    预览图
    operationVerificationCodeImage.png

    总的来说,AWT实现验证码非常简单,只需要编写简单的逻辑即可实现需要的验证码功能。代码中的验证码可以根据字符长度和运算表达式长度适应画布大小。但是,仍是不完美;这时,kaptcha就登场了,我们为啥要使用kapcha,kapcha的优势有什么?
    kaptcha验证码是谷歌编写开源的,也是基于AWT实现。但是功能更加丰富,可以配置背景、画布、尺寸、颜色、样式、噪点等等诸多好处。项目具有轻量级、功能丰富、易于上手,且是大公司开源,稳定性有保障。为何不用?

    kaptcha实现字符验证码:
    默认情况下,kaptcha是默认生成英文数字组合的字符验证码。但是,这里功能很强大,可以自己编写验证码的生成器规则,注册到kapcha拦截器中,即可使用。运算验证码就是使用这一种方式,待会再议。

    配置类代码:

    @Configuration
    public class CaptchaConfig
    {
        @Bean(name = "captchaProducer")
        public DefaultKaptcha getKaptchaBean()
        {
            DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
            Properties properties = new Properties();
            // 是否有边框 默认为true 我们可以自己设置yes,no
            properties.setProperty("kaptcha.border", "yes");
            // 边框颜色 默认为Color.BLACK
            properties.setProperty("kaptcha.border.color",  "black");
            // 验证码文本字符颜色 默认为Color.BLACK
            properties.setProperty("kaptcha.textproducer.font.color", "black");
            // 验证码图片宽度 默认为200
            properties.setProperty("kaptcha.image.width", "150");
            // 验证码图片高度 默认为50
            properties.setProperty("kaptcha.image.height", "60");
            // 验证码文本字符大小 默认为40
            properties.setProperty("kaptcha.textproducer.font.size", "30");
            // KAPTCHA_SESSION_KEY
            properties.setProperty("kaptcha.session.key", "kaptchaCharCode");
            // 验证码文本字符间距 默认为2
            properties.setProperty("kaptcha.textproducer.char.space", "3");
            // 验证码文本字符长度 默认为4
            properties.setProperty("kaptcha.textproducer.char.length", "4");
            // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
            properties.setProperty("kaptcha.textproducer.font.names", "微软雅黑");
            // 验证码噪点颜色 默认为Color.BLACK
            properties.setProperty("kaptcha.noise.color",  "black");
            Config config = new Config(properties);
            defaultKaptcha.setConfig(config);
            return defaultKaptcha;
        }
    }
    

    生成字符验证码

     /**
         * 获取字符验证码
         *
         * @param imageVerificationDto 用户信息
         * @return 字符验证码
         * @throws ServiceException 获取字符验证码异常
         */
        private ImageVerificationVo selectCharVerificationCode(ImageVerificationDto imageVerificationDto) throws ServiceException {
    
            byte[] bytes = null;
            String text = "";
            BufferedImage bufferedImage = null;
            ImageVerificationVo imageVerificationVo = null;
    
            try {
    
                imageVerificationVo = new ImageVerificationVo();
                //  生成字符验证码文本
                text = captchaProducer.createText();
                //  生成字符验证码图片
                bufferedImage = captchaProducer.createImage(text);
                getRequest().getSession().setAttribute("imageVerificationVo", imageVerificationVo);
                //  在分布式应用中,可将session改为redis存储
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
                bytes = byteArrayOutputStream.toByteArray();
                //  图片base64加密
                imageVerificationVo.setCharImage(Base64Utils.encodeToString(bytes));
                imageVerificationVo.setType(imageVerificationDto.getType() == null ? "char" : imageVerificationDto.getType());
    
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new ServiceException(ServiceExceptionCode.SELECT_VERIFICATION_CODE_ERROR);
            }
            return imageVerificationVo;
    
        }
    

    预览图
    QQ截图20190821105231.png

    kaptcha实现运算验证码

    配置类

    @Configuration
    public class CaptchaConfig
    {
    @Bean(name = "captchaProducerMath")
        public DefaultKaptcha getKaptchaBeanMath()
        {
            DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
            Properties properties = new Properties();
            // 是否有边框 默认为true 我们可以自己设置yes,no
            properties.setProperty("kaptcha.border", "no");
            // 边框颜色 默认为Color.BLACK
            properties.setProperty("kaptcha.border.color", "55,160,204");
            // 验证码文本字符颜色 默认为Color.BLACK
            properties.setProperty("kaptcha.textproducer.font.color", "blue");
            // 背景渐变色,开始颜色
            properties.setProperty("kaptcha.background.clear.from", "234,172,236");
            // 背景渐变色,结束颜色
            properties.setProperty("kaptcha.background.clear.to", "234,144,115");
            // 验证码图片宽度 默认为200
            properties.setProperty("kaptcha.image.width", "170");
            // 验证码图片高度 默认为50
            properties.setProperty("kaptcha.image.height", "60");
            // 验证码文本字符大小 默认为40
            properties.setProperty("kaptcha.textproducer.font.size", "35");
            // KAPTCHA_SESSION_KEY
            properties.setProperty("kaptcha.session.key", "kaptchaMathCode");
    // --------------验证码文本生成器,这里需要设置成自己项目的包名----------------------
            properties.setProperty("kaptcha.textproducer.impl", "com.selfimpr.captcha.config.KaptchaMathTextCreator");
            // 验证码文本字符间距 默认为2
            properties.setProperty("kaptcha.textproducer.char.space", "3");
            // 验证码文本字符长度 默认为9
            properties.setProperty("kaptcha.textproducer.char.length", "9");
            // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
            properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
            // 验证码噪点颜色 默认为Color.BLACK
            properties.setProperty("kaptcha.noise.color", "243,79,67");
            // 干扰实现类
    //        properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
            // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
    //        properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
            Config config = new Config(properties);
            defaultKaptcha.setConfig(config);
            return defaultKaptcha;
        }
    }
    
    

    注意。这里注册了自定义验证码生成器
    image.png

    自定义运算器,同AWT生成运算验证码的运算方法没有区别。

    package com.selfimpr.captcha.config;
    
    
    import com.google.code.kaptcha.text.impl.DefaultTextCreator;
    
    import java.util.Random;
    
    /**
     * @Description: 运算验证码
     * -------------------
     * @Author: YangXingfu
     * @Date: 2019/07/12 09:11
     */
    
    public class KaptchaMathTextCreator extends DefaultTextCreator {
    
        StringBuilder result = new StringBuilder();
    
    
        @Override
        public String getText() {
            Random random = new Random(System.currentTimeMillis());
            int x = random.nextInt(51);
            int y = random.nextInt(51);
            int operationalRules = random.nextInt(4);
    
            switch (operationalRules) {
                case 0 : add(x, y); break;
                case 1 : subtract(x, y); break;
                case 2 : multiply(x, y); break;
                case 3 : divide(x, y); break;
            }
            return result.toString();
        }
        
        private void add(int x, int y) {
            result.append(x);
            result.append(" + ");
            result.append(y);
            result.append(" = ?@");
            result.append(x + y);
        }
    
        private void subtract(int x, int y) {
            int max = Math.max(x, y);
            int min = Math.min(x, y);
            result.append(max);
            result.append(" - ");
            result.append(min);
            result.append(" = ?@");
            result.append(max - min);
        }
    
        private void multiply(int x, int y) {
            int value = x * y;
            result.append(x);
            result.append(value > 100 ? " + " : " * ");
            result.append(y);
            result.append(" = ?@");
            result.append(value > 100 ? x + y : x * y);
        }
    
        private void divide(int x, int y) {
            int max = Math.max(x, y);
            int min = Math.min(x, y);
            if (min == 0) {
                multiply(max, min);
            } else if(max % min == 0) {
                result.append(max);
                result.append(" / ");
                result.append(min);
                result.append(" = ?@");
                result.append(max / min);
            } else {
                result.append(max);
                result.append(" % ");
                result.append(min);
                result.append(" = ?@");
                result.append(max % min);
            }
        }
    
    }
    

    生成运算验证码

    **
         * 获取运算验证码
         *
         * @param imageVerificationDto 用户信息
         * @return 运算验证吗
         * @throws ServiceException 查询运算验证码异常
         */
        private ImageVerificationVo selectOperationVerificationCode(ImageVerificationDto imageVerificationDto) throws ServiceException {
    
            byte[] bytes = null;
            String text = "";
            BufferedImage bufferedImage = null;
            ImageVerificationVo imageVerificationVo = null;
    
            try {
    
                imageVerificationVo = new ImageVerificationVo();
                imageVerificationVo.setType(imageVerificationDto.getType());
                //  生成运算验证码文本
                text = captchaProducerMath.createText();
                String value = text.substring(0, text.lastIndexOf("@"));
                //  生成运算验证码图片
                bufferedImage = captchaProducerMath.createImage(value);
                //  验证码存入redis
                getRequest().getSession().setAttribute("imageVerificationVo", imageVerificationVo);
                //  在分布式应用中,可将session改为redis存储
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
                bytes = byteArrayOutputStream.toByteArray();
                //  图片base64加密
                imageVerificationVo.setOperationImage(Base64Utils.encodeToString(bytes));
                imageVerificationVo.setType(imageVerificationDto.getType());
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new ServiceException(ServiceExceptionCode.SELECT_VERIFICATION_CODE_ERROR);
            }
            return imageVerificationVo;
    
        }
    

    image.png

    ####后话
    这里的验证码样式、字体等都有点丑,原谅作者的艺术水平太高,大大们可自行调整。kapcha验证码与手动编写的验证码可以明显看出kaptcha验证码的优势,推荐大家使用kaptcha来做验证码。
    有了这些验证码为什么会有新的验证码?值得大家思考的一个问题。

    项目地址:https://gitee.com/gester/captcha.git

    如果这篇文章有帮您,可以给个star,谢谢大大。

    同时,推荐一波当下流行的滑动验证码,验证码实现和京东的滑动验证码没有多大区别。下面给个传送门,给个预览图哈。
    Java滑动验证码的原理与实现文章地址:https://blog.csdn.net/YTenderness/article/details/99969355
    1.png

    展开全文
  • CSS字母间距(letter-spacing)和字符串全长的关系 问题来源 这是一个用canvas手动实现的富文本编辑的模块,发现了字符串宽度大于元素width导致了异常的显示。 分析过程 然而,所有的文字属性皆从一个用CSS版本的...
  • java字符串分割方法

    2021-11-17 22:37:51
    java 分割字符串split()方法 实现功能 编写一个将字符串分段的类,传入:需分段的字符串 与 字符个数(以此个数进行分段),输出:按指定字符个数进行分段后的若干字符串(汉字算单个字符)。 功能实现要求分析 ...
  • Java怎么调整字符间距

    2012-08-23 17:36:45
    文本框中输入的字符都连在一起,有没有办法让字符字符之间的距离加大,就像CSS的word-spacing的功能。 [img=http://61.164.105.126/1/11.jpg][/img] 如上图,用户名的字感觉都合在一起了。
  • java操作图片,给一个大图片贴小图片,给图片添加文字并调整文字颜色,大小,字体间距,把本地图片或者网络图片加载到缓冲区 主要方法: imageIoRead方法,把图片加载到缓冲区 mergeImage方法,给一张图片贴 图片,...
  • 今天要谈的是如何在Java中调整字距与行距,当然,这里谈的主要是针对swing与awt里的字距与行距。调整字距与行距看起来似乎是个很简单的问题,大概可以直接调用某个内置的方法来操作,紫雾我最开始也是这么觉得的,但...
  • 从前往后数,每隔5个字符插入一个 @ 字符一般情况下,从前往后数,每5个字符之间依次,插入@进去;最后一组字符,不插入 @ ;例如:12345@12345@123 12345@12345说明: 以几个字符为间隔,那么就设定 i 变量的步长为几;var...
  • 我已经开始在JavaFX中开发一个应用程序而且我遇到了一个问题,我发现很少有用的信息:Linux中字符之间的间距非常不均匀.我不是在谈论不同角色的宽度,而是在谈论角色之间的空间.它在普通文本中可见,但以下示例比普通...
  • 一,首先我们来大体梳理一下Scanner类: 1.Scanner类是为获取用户的输入 ...(1)String next()查找并返回来自此扫描器的下一个完整标记, 获取一个字符串 注意: next()必须得到有效字符 next()获取第...
  • Java格式化字串输出固定长度

    千次阅读 2019-11-30 19:43:14
    Java格式化字串输出固定长度
  • leetcode数组下标大于间距 implement data structure and algorithms data_struct: 主要包括数据结构的java实现 1.数组 2.并查集 3.图 4.链表 5.队列 6.栈 7.树 divide_conquer:分治 1.活动选择问题 2.输入一个整形...
  • 使用Java写出一个程序:接受一个由字母和数字组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。
  • 添加模板 添加文本内容 设置文本字体 设置文本字体大小 设置字体颜色 设置表单域颜色 组件方法调用: ...addText(String templKey,String key,String text), 向模板中一个表单域添加一个文本数据;...
  • 1 2 ...封装的可以控制往图片上写字,控制字符间距的方法 本文转自 陈小龙哈 51CTO博客,原文链接: http://blog.51cto.com/chenxiaolong/1716746
  • 给你一个字符串s,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 示例 1: 输入:s = "bcabc" 输出:"abc" 注意:该题与 1081. 不同...
  • 最大间距 描述:给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。如果数组元素个数小于 2,则返回 0。 示例1: 输入: [3,6,9,1] 输出: 3 解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) ...
  • java"] public String bSubstring(String s, int length) throws Exception{ byte[] bytes = s.getBytes("Unicode"); int n = 0; // 表示当前的字节数 int i = 2; // 要截取的字节数,从...
  • 问题:给一个全是小写字母的字符串和一个字符串之间间隔的数字,要求输出一个相同字母之间距离不超过间隔数的字符串,如果无法生成这样的字符串就输入“”。 例子1:"xxyyz", 间隔2 输出:"xyxyz",第一个x和第...
  • 在控制台手操时,结果很正常,使用java操作发现返回的结果固定为80个字符宽,原本在控制台的一行超过80字符Java里就得换行,导致图表都乱了。 根据http://www.cnpaf.net/Class/Telnet/200408/6.html的文章得到...
  • 疯狂JAVA讲义

    2014-10-17 13:35:01
    学生提问:图11.15和图11.16显示的所有按钮都紧挨在一起,如果希望像FlowLayout、GridLayout等布局管理器指定组件的间距该怎么办? 397 11.4 AWT 常用组件 398 11.4.1 基本组件 398 11.4.2 对话框 400 11.5 事件...
  • 定义两个指针pStr1和pStr2分别指向字符串的头和尾。定义map strMap,保存字符和对应的最大间隔。保持pStr1不变,如果pStr1和pStr2指向的字符相等,则在strMap中保存strMap[str[pStr1]] = pStr2 - pStr1; 否则pStr2...
  • 从概念上讲,Java字符串是Unicode字符的序列。例如,字符串“Java\u2122”由五个Unicode字符J、A、V、A和μ组成。Java没有内置的字符串类型。相反,标准Java库包含一个预定义类,称为字符串。每个带引号的字符串都是...
  • LetterSpacingTextView.java package com.akm.akmviewpager;/** * Created by toge on 16/1/... * 字间距 */import android.content.Context; import android.content.res.TypedArray; import android.text.Spannable
  • HTML标签常用标签

    千次阅读 多人点赞 2017-02-23 11:33:58
    1、 注释标签  注释标签用于在源代码中插入注释。注释不会显示在浏览器中。 2、  声明标签 声明必须是 HTML 文档的第一行,位于 标签之前。 声明不是 HTML 标签;它是指示 web 浏览器关于页面使用...包含所有

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,389
精华内容 3,755
关键字:

java字符间距

java 订阅