平时除了工作,还要为自己的理想而奋斗,很少有时间来写博客。今天加班,但是却很空闲,于是把有些东西拿出来整理整理。
近来一直在做一个基于Struts的Java Web日本项目,没有什么高深的技术问题,一切都还是蛮顺利的。期间遇到了一个用户注册信息规则检测的问题,我觉得解决问题的方法和获得的经验很值得程序员朋友们借鉴,特地拿出来和大家分享一下。
对于大多数Web项目,用户注册信息规则检测都是一个必须面对的问题。之所以把这个问题特别的拿出来讲,是因为这次我所面临的检测条件相对比较复杂一点(知道了其实也很简单,也是经验值不足的表现,哈哈…),然而又不缺乏普遍性。
下面我就拿项目中的用户名规则检测作为例子来讲。
“用户名”规则:
1. 文字规则:中文、日文、数字、英文字母的全/半角输入均可。
2. 特殊符号规则:只允许半角記号 .(点) -(横杠)_(下划线)。
3. 长度规则:最大半角20文字。
其实遇到字符串的匹配问题,我们都很容易联想到解决这个问题的有力工具——正则表达式。当然我也看见过很“勇敢”的人,他们不用正则表达式来实现,而是自己写很长很长的代码一个符号一个符号来判断或者排除。我见过一个日本人写的字符串规则检测代码,是用JavaScript写的,足足4000多行代码。一看,我就晕了o(∩_∩)o…
言归正传,还是说说我们怎么用正则表达式来解决这个问题的吧。
其实,不用头脑我们也可以想象得到一个一个字符进行排除这种检测方法根本不现实也不可靠,那特殊字符、中文、日文、韩文、阿拉伯文,还有很多不知名的文字符号,数不胜数,你能保证列举完吗?既然正面处理不行,我们就反其道而行之——只要是存在不合法的字符就报错。这样,问题就简单了。
对于上述的例子,我们只需要知道中文、日文、数字、英文字母的全/半角Unicode编码范围就万事大吉了。怎么获得呢?
首先讲讲任意字符的Unicode编码(这里指常用的UCS-2,它可以表示的字符数为2^16=65535,基本上容纳了所有的欧美字符和亚洲字符)获取。我写了下面一段Java代码来实现。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GetUnicodeNO {
public final static int UNICODE_NO_LENGTH = 4;
public static String inputCharacters() {
String characters = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
characters = in.readLine().trim();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return characters;
}
public static String outputFormat(String hexNum) {
String str = "//u" + hexNum;
for (int i = UNICODE_NO_LENGTH; i > hexNum.length(); i--) {
str += "0";
}
return str;
}
public static void output(char character, int unicodeNO) {
System.out.println("" + character + "/t-->/t"
+ outputFormat(Integer.toHexString(unicodeNO).toUpperCase()));
}
public static void countUnicodeNO(String characters) {
int unicodeNO;
for (int i = 0; i < characters.length(); i++) {
unicodeNO = (int) characters.charAt(i);
output(characters.charAt(i), unicodeNO);
}
}
public static void main(String[] args) {
while(true){
System.out.println("Please input characters:");
countUnicodeNO(inputCharacters());
}
}
}
其实,我们还有一个捷径来获取字符的Unicode编码——微软的word。选择“插入”à“符号”,看到了吧。几乎所有的欧美字符和亚洲字符的Unicode编码都在这里了,直观呀!
我们很容易就得到各种字符的编码范围。
中文:/u4E00-/u9FA5
日文的平假名/片假名:/u3041-/u30FE
全角符号:/uFF00-/uFFFF
数字和字母:/w(匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_])
好了,剩下的就是正则表达式的书写了。只要存在非以上字符,那就不符合规则。用正则表达式表达也就是:
<input onkeyup=
"value=value.replace(/[^/u4E00-/u9FA5/|^/u3041-/u30FE/|^/uFF00-/uFFFF/|^/w/-/.]/g,’’)"
>
哈哈,连JS脚本都免掉了。
当然,如果你想用在用户输入完毕后再进行检测也是可以的。我们只需要把它写成一个函数(如checkInput()),然后在表单Form中写上onsubmit="return checkInput()"调用就可以了。
function checkInput(){
if(userName.match(/[^/u3041-/u30FE/|^/u4E00-/u9FA5/|^/w/-/.]/g)!=null){
alert(“userName中有非法字符”);
return false;
}
}
关于一般的输入规则检测,下面再给出几个例子:
1. 只允许输入数字:
<input onkeyup="value=value.replace(/[^/d]/g,'')">
2. 只允许输入符号:
<input onkeyup="value=value.replace(/[/W]/g,'')">
3. 只允许输入全角:
<input onkeyup="value=value.replace(/[^/uFF00-/uFFFF]/g,'')">
4. 只允许输入汉字:
<input onkeyup="value=value.replace(/[^/u4E00-/u9FA5]/g,'')">
正如孟岩在他的《<精通正则表达式>书评》中所写到的——如果罗列计算机体系结构领域里中的伟大发明,除了分组交换网络、Web、Lisp、哈希算 法、UNIX、编译技术、关系模型、面向对象、XML这些大名鼎鼎的家伙之外,正则表达式也绝对不应该被漏掉。正则表达式具有伟大技术发明的一切特点,它简 单,优美,功能强大,妙用无穷。
至于条件3,用下面一段JS就行了:
function getLen(sString){
var sStr,iCount,i,strTemp ;
iCount = 0 ;
sStr = sString.split("");
for (i = 0 ; i < sStr.length ; i ++){
strTemp = escape(sStr[i]);
if(strTemp.indexOf("%u",0) == -1){
iCount = iCount + 1 ;
}else{
iCount = iCount + 2 ;
}
}
return iCount ;
}
感悟:一个好的工具和解决问题的思想可以大大简化我们的工作。