package me.test; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import nl.captcha.text.producer.TextProducer; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An alternative to SimpleCaptcha's {@link nl.captcha.text.producer.ChineseTextProducer ChineseTextProducer} which may * using rarely used characters 。 * This class will only generate text using level of commonly used Chinese characters. *<p> * Reference: <a href="http://en.wikipedia.org/wiki/GB_2312">GB2312</a>, * <a href="http://en.wikipedia.org/wiki/GBK">GBK</a>, * <a href="http://en.wikipedia.org/wiki/ISO_2022">ISO2022</a> * </p> */ public class MyChineseTextProducer implements TextProducer { private CharsetDecoder gbkCharsetDecoder = Charset.forName("GBK").newDecoder(); private SecureRandom random; private final int count; private StringBuilder strBuf; private ByteBuffer byteBuf = ByteBuffer.allocate(2); private CharBuffer charBuf = CharBuffer.allocate(2); private Logger logger = LoggerFactory.getLogger(MyChineseTextProducer.class); public MyChineseTextProducer() { this(6); } public MyChineseTextProducer(int count) { this.count = count; this.strBuf = new StringBuilder(count); try { this.random = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } } public synchronized String getText() { strBuf.setLength(0); for (int i = 0; i < this.count; i++) { strBuf.append(getRandomClass1ChineseChar()); } return strBuf.toString(); } /** * get a random Chinese character in first plane for Chinese characters. * * @return a Chinese character */ private char getRandomClass1ChineseChar() { byteBuf.clear(); charBuf.clear(); gbkCharsetDecoder.reset(); // 区:16~55 byte zone = (byte) (this.random.nextInt(55 - 16 + 1) + 16); // 位:01~94 byte position = (byte) (this.random.nextInt(94) + 1); byteBuf.put((byte) (zone + 0xA0)); byteBuf.put((byte) (position + 0xA0)); byteBuf.rewind(); charBuf.rewind(); gbkCharsetDecoder.decode(byteBuf, charBuf, true); char chineseChar = charBuf.get(0); if (logger.isDebugEnabled()) { logger.debug("using chinese character : [{},{}] = 0x{} '{}'", zone, position, Hex.encodeHexString(byteBuf.array()).toUpperCase(), chineseChar); } return chineseChar; } public static void main(String[] args) { TextProducer t = new MyChineseTextProducer(); for (int i = 0; i < 10; i++) { System.out.println(t.getText()); } } }