使用正则表达式验证本地化数据

数据验证是编写任何用户界面时经常要处理的一项杂务。Java™ 语言的正则表达式支持可以使数据验证变得更容易。您可以定义一个正则表达式,用于描述有效数据,然后让 Java 运行时检查它是否匹配。但是有些类型的数据在不同地区有不同的格式。而 ResourceBundle 类让您可以以一种优雅的方式使用特定于地区的数据。本文展示如何结合这两种技术来解决常见的数据输入问题。

本文讨论将正则表达式与 Java ResourceBundle 相结合的一种数据验证技术。Java 语言对正则表达式的支持可以大大简化数据验证。您可以将数据与正则表达式进行比较,如果它们匹配,则知道数据是有效的。另一方面,Java ResourceBundle 包含翻译好的字符串,用于匹配用户机器上的当前语言和国家设置。ResourceBundle 中的字符串通常是出现在应用程序中的文本,但是也可以是特定于某个地区的任何东西。

您将实践一个示例应用程序,该应用程序从 ResourceBundles 获得正则表达式,并将它们用于数据验证(请参见 下载 小节)。通过这种方法,就可以用一块代码来验证很多不同类型的数据。更妙的是,随着更多 ResourceBundle 的添加,还可以验证更多类型的数据,并且不用更改这段代码中的任何一行。

本文的示例应用程序是在 Eclipse 中用 Visual Editor 构建的。Visual Editor 是一种用于构建图形化界面的开放源码工具。为了构建自己的应用程序,您需要在计算机上安装 Eclipse 和 Visual Editor 包(请参阅 参考资料)。这个示例应用程序只是举例说明了验证数据的一种技巧,所以这种方法可用于任何 Java 应用程序。

示例应用程序

我不想花太多的时间讨论这个示例应用程序的所有细节,我只关注其中的数据验证方面的技巧。这个应用程序验证输入到输入域中的邮政编码。您可能知道,在世界的不同地方,邮政编码千差万别。有的是数字,有的则包含字母。即使同是由数字组成的邮政编码,在不同地方其长度也不尽相同。有的国家以特定的模式排列字母和数字,而另外一些国家则采用更自由的格式。所有这些格式都可以用正则表达式来描述。例如,在美国邮政编码是一个五位数,后面还可能跟有一个破折号加一个四位数。清单 1 展示了描述这种格式的正则表达式:

清单 1. 用于美国邮政编码的正则表达式

[0-9]{5}(-[0-9]{4})?

除了格式不同外,邮政编码并不总是被称为邮政编码。例如,美国将邮政编码称为 ZIP Code。ResourceBundle 的一种常见用法就是处理这种类型的与地区有关的差异。用于美国的 ResourceBundle 可能包含短语 "Enter your ZIP Code",而在用于加拿大的 ResourceBundle 中,相应的短语可能是 "Enter your postal code"。我在本文中演示的技巧也是从 ResourceBundle 获得用于有效邮政编码的正则表达式。

为了使这个示例简单化,您将创建一个只有一个输入域和一个 Validate 按钮的 Swing 应用程序。用户在输入域中输入文本,然后单击该按钮。如果数据与当前的正则表达式匹配,则应用程序显示一条消息,表明邮政编码有效。因为应用程序使用不同的 ResourceBundle,所以正则表达式随着有效数据的规则的变化而变化。由于正则表达式是从文本文件中装载的一个字符串,所以当添加对新类型的邮政编码的支持时,不需要更改代码。

您将在 Eclipse 中使用 Eclipse Visual Editor 和 Eclipse Java Development Tool 的一些特性来构建这个应用程序。您可以在几乎所有开发环境中使用这种技巧。这里的代码应该可以在任何基于 Eclipse 的产品中运行,例如 Rational Application Developer(请参阅 参考资料)。

图 1 展示了该应用程序在 Eclipse Visual Editor 中的样子:

图 1. Eclipse Visual Editor 中的示例应用程序

Visual Editor 提供了四种查看应用程序的方式。在屏幕的顶端是应用程序的可视化图像,源代码在底端。Eclipse 还提供了两个视图 —— Properties 视图和 Java Beans 视图 —— 可以通过这两个视图来处理应用程序。所有这些查看应用程序的方式都是由 Eclipse Modeling Framework (EMF) 控制的。由于已经有一些关于 EMF 的完整书籍,所以我不会再谈更多的细节。从程序员的角度来看,重要的一点是,任何视图中的变化都会自动发送到其他视图。例如,如果您使用 Properties 视图将一个对象的背景颜色设为绿色,那么可视化图像和源代码也会自动更新。


回页首

运行初始的示例应用程序

首先来看一个已经创建好的应用程序(参见 下载 小节)。图 2 展示了这个应用程序的运行界面:

图 2. 输入有效数据时的示例应用程序

在图 2 中,用户输入了有效的数据,并单击了 Validate 按钮。如果数据无效,那么将出现图 3 所示的界面:

图 3. 输入无效数据时的示例应用程序

清单 2 展示了如何使用 清单 1 中的正则表达式来验证数据:

清单 2. 使用正则表达式

Pattern pc = Pattern.compile("[0-9]{5}(-[0-9]{4})?");
Matcher m = pc.matcher(postalCode.getText());
if (m.matches())
{validLabel.setText("Your postal code is valid.");validLabel.setForeground(Color.BLUE);
}
else
{validLabel.setText("Your postal code is not valid."); validLabel.setForeground(Color.RED);
}

清单 2 中的两条反馈消息通常会被翻译成其他语言。您还将通过使用这里展示的技巧来 “翻译” 正则表达式。与一般的翻译不同,将正则表达式转换成国际化版本是数据格式专家的工作,而不是语言专家的工作。


回页首

具体化字符串

Eclipse 为代码的国际化提供了一个方便的特性。首先单击 Source > Externalize Strings...,如图 4 所示:

图 4. Externalize Strings... 主菜单

Eclipse 查看 Java 代码,以发现应该放入到 ResourceBundle 中的字符串。您将看到类似图 5 所示的对话框:

图 5. Externalize Strings 对话框

在图 5 中列出的所有字符串中,对话框顶部的空白字符串不需要翻译。(反馈消息的初始值是一个空白字符串。)取消对第一个字符串的选择,然后单击 NextFinish。Eclipse 创建一个新的名为 com.ibm.developerworks.Messages 的类,这个类从 messages.properties 文件获取字符串。


回页首

处理国际化代码

具体化代码之后,Eclipse 修改初始的类,将字符串移入 messages.properties 文件,并创建一个名为 Messages 的新类。Messages 类有一个名为 getString() 的静态方法,应用程序将使用该方法来获得字符串的值。

Messages 类在内部使用 ResourceBundle。清单 3 展示了生成的用于创建 ResourceBundle 的代码:

清单 3. 创建 ResourceBundle

public class Messages {private static final String BUNDLE_NAME ="com.ibm.developerworks.messages"; //$NON-NLS-1$private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);

稍后我将更详细地谈到如何创建 ResourceBundle。

所有字符串的值都在 messages.properties 文件中,如清单 4 所示:

清单 4. messages.properties 文件

LocalizedValidator.1=News Gothic
LocalizedValidator.2=Validate
LocalizedValidator.3=[0-9]{5}(-[0-9]{4})?
LocalizedValidator.4=Your postal code is valid.
LocalizedValidator.5=Your postal code is not valid.
LocalizedValidator.6=Exit
LocalizedValidator.7=Localized Data Validator
LocalizedValidator.8=Enter your postal code, then click Validate:

从技术上说,该文件是 com/ibm/developerworks/messages.properties,但是您不必关心这个细节。生成的代码可以正确无误地找到该文件。


回页首

使用 ResourceBundle 来验证数据

当使用 Eclipse Externalize Strings 功能创建 .properties 文件时,它修改了应用程序,以便同时获取正则表达式和程序中所有其他可翻译的文本,如清单 5 所示:

清单 5. 通过 ResourceBundle 使用正则表达式

Pattern pc = Pattern.compile(Messages.getString("LocalizedValidator.3"));
//$NON-NLS-1$
Matcher m = pc.matcher(postalCode.getText());
if (m.matches())
{validLabel.setText(Messages.getString("LocalizedValidator.4"));
//$NON-NLS-1$validLabel.setForeground(Color.BLUE);
}
else
{validLabel.setText(Messages.getString("LocalizedValidator.5"));
//$NON-NLS-1$validLabel.setForeground(Color.RED);
}

注意,Pattern.compile() 方法使用 Messages.getString() 方法来获得正则表达式的值。当需要验证数据时,代码首先获得字符串 LocalizedValidator.3,然后使用它来验证邮政编码。反馈消息也是从 properties 文件获得的。


回页首

如何装载 .properties 文件

至此,主应用程序已经可以使用 “翻译” 好的正则表达式了。所有字符串的值都来自 messages.properties 文件,那么,如何装载这些字符串的不同版本呢?答案取决于 ResourceBundle 是如何创建的。

无论何时运行一个 Java 程序,它都有一个特定的地区。地区由两个字母的语言代码和两个字母的国家代码来指定,这些代码是由 ISO 标准定义的。地区代码还有一个不常用的变种部分,用于更精确地指定特定的地区。下面是一些例子:

  • en_US 是 U.S. English 地区。
  • en_CA 是 Canadian English 地区。
  • fr_CA 是 French Canadian 地区。
  • en 是 English 地区。
  • en_US_UNIX 是 U.S. English 地区的 UNIX 变种。至于该变种的意义及其用法,是由应用程序的编写者定义的。

当创建一个新的 ResourceBundle 时,Java 运行时根据当前的地区查找文件。例如,如果当前地区是 en_US,那么 Java 运行时依次查找以下文件:

  1. messages_en_US.properties
  2. messages_en.properties
  3. messages.properties

当 ResourceBundle 收集翻译好的字符串时,在 messages_en_US.properties 中发现的任何字符串都具有比 messages_en.properties 和 messages.properties 中具有相同名称的字符串更高的优先级。如果运行时没有发现任何特定于地区的文件,那么它将使用 messages.properties 中的字符串。

记住,创建 ResourceBundle 的代码指定了文件名 messages.properties。该文件名不会随着地区的改变而改变,这意味着您的代码也不需要做出更改。您只需指定这个文件名,Java 运行时可以自动得出应该装载哪个特定于地区的文件。


回页首

特定于地区的 .properties 文件

一个特定于地区的 .properties 文件只包含不同于更通用的 .properties 文件的字符串。例如,如果 messages_en.properties 文件包含 LocalizedValidator.9=What is your favorite color? 这一行,那么 messages_en_GB.properties 文件可能包含 LocalizedValidator.9=What is your favourite colour?。如果只有这个英国化的字符串是 en_GB 地区所特有的,那么 messages_en_GB.properties 文件只需包含这个字符串。当代码向 ResourceBundle 请求任何其他字符串时,如果 messages_en.properties 中有这样的字符串,就使用其中的字符串。如果 messages_en.properties 文件中没有那样的字符串,则使用 messages.properties 中的版本。如果这一系列的 .properties 文件中都没有被请求的字符串,就会抛出 java.util.MissingResourceException 异常。

清单 6 展示了美国地区的 .properties 文件所特有的一些行:

清单 6. en_US(美国)地区特有的值

LocalizedValidator.4=Your ZIP Code is valid.
LocalizedValidator.5=Your ZIP Code is not valid.
LocalizedValidator.8=Enter your ZIP Code, then click Validate:

这里惟一的变化是使用 "ZIP Code" 代替 "postal code"。可用默认的正则表达式验证该数据。

英国的邮政编码有六种不同的格式,还有一个特殊的值 GIR 0AA,如清单 7 所示。(为了便于阅读,清单 7 中的正则表达式被分成两行,实际上只有一行。)

清单 7. en_GB(英国)地区特有的值

LocalizedValidator.3=[A-Z]([0-9]|[0-9]{2}|[A-Z][0-9]|[A-Z][0-9]{2}|[0-9][A-Z]|[A-Z][0-9][A-Z]) [0-9][A-Z]{2}|GIR 0AA
LocalizedValidator.8=Enter your postcode, then click Validate:

用于澳大利亚的正则表达式包括州或地区的简称,需要的空格(一个或两个),以及一个四位数,如清单 8 所示:

清单 8. en_AU(澳大利亚)地区特有的值

LocalizedValidator.3=(ACT|NSW|NT|QLD|SA|TAS|VIC|WA)( |  )[0-9]{4}
LocalizedValidator.8=Enter your Australian postal code, then click Validate:

加拿大的邮政编码格式是字母、数字、字母、一个空格、数字、字母、数字,如清单 9 所示:

清单 9. en_CA(加拿大)地区特有的值

LocalizedValidator.3=[A-Z][0-9][A-Z] [0-9][A-Z][0-9]
LocalizedValidator.8=Enter your Canadian postal code, then click Validate:

清单 10 展示了德国地区特有的值。德国的邮政编码是一个五位数:

清单 10. de(德国)地区特有的值

LocalizedValidator.2=Validieren
LocalizedValidator.3=[0-9]{5}
LocalizedValidator.4=Ihre Postleitzahl ist gÜltig
LocalizedValidator.5=Ihre Postleitzahl ist ungÜltig!
LocalizedValidator.6=Beenden
LocalizedValidator.7=NLS Datenvalidatung
LocalizedValidator.8=Geben Sie Ihre Postleitzahl ein

回页首

在运行时设置地区

现在您已经定义了 .properties 文件,接下来应该用两种方法中的一种来测试这些文件。第一种方法是在运行应用程序的时候设置 user.language 和 user.country 这两个系统属性。在 Eclipse 环境中,可以右键单击一个类名,然后选择 Run... 菜单,如图 6 所示:

图 6. Run... 菜单

在 Run 对话框中,可以设置 Java VM 选项,以改变默认的语言和地区,如图 7 所示:

图 7. 在 Run 对话框中设置 Java VM 参数

-D 选项用于定义系统属性。您可以在命令行中使用相同的语法,例如:

java -Duser.language=en -Duser.country=AU com.ibm.developerworks.LocalizedValidator

第二种方法是在应用程序中设置地区。通过 Locale.setDefault() 方法可以在代码中设置默认的地区。清单 11 展示了如何改变 LocalizedValidator 类的 main() 方法:

清单 11. 在应用程序中设置默认的地区

public static void main(String[] args) {String language = "";String country = "";if (args.length > 0)language = args[0];if (args.length > 1)country = args[1];Locale.setDefault(new Locale(language, country));LocalizedValidator nv = new LocalizedValidator();nv.show();
}

如果在命令行没有指定参数,则使用用户计算机的默认地区。如果没有命令行参数,则代码 new Locale("", "") 只是创建默认的地区。

也可以在 Run 对话框中设置命令行参数,如图 8 所示:

图 8. 在 Run 对话框中设置命令行参数

图 9 展示了指定了参数 en AU 的情况下应用程序的界面:

图 9. 用于澳大利亚地区(en_AU)的示例应用程序

用参数 de 运行示例应用程序时,将得到如图 10 所示的界面:

图 10. 用于德国地区(de)的示例应用程序


回页首

结束语

本文展示了如何将正则表达式与 Java 语言的国际化支持相结合来验证不同类型的本地化数据。通过这种技巧,您可以支持新的数据类型,而不用更改任何代码。例如示例应用程序,如果您想添加对波兰的邮政编码的支持,那么只需创建一个 messages_pl.properties 文件。这样就在没有更改任何代码的情况下添加了对新数据类型的支持。(如果您想知道的话,那么告诉您,用于波兰的邮政编码的正则表达式是 [0-9]{2}-?[0-9]{3}。)

示例应用程序原封不动地使用 Eclipse 生成的 Messages 类。这个类能满足这个例子的要求,但是,应用程序启动时会装载 ResourceBundle,并且直到下次运行应用程序时才能重新装载 ResourceBundle。如果您想更改代码,以便动态地改变 ResourceBundle,那么需要修改 Messages 类,使它的字段和方法不是静态的。这做起来不难,但是您还需要修改和维护 Messages.java 文件。就把这个任务作为练习吧。

还应该认识到,Swing 提供了 javax.swing.JFormattedTextField 类。利用这个类可以为文本域定义一个掩码。例如,您可以使用掩码 (###) ###-####,使用户只能在文本域中输入有效的美国的电话号码。您可以使用与这里相同的技巧来从一个本地化的 ResourceBundle 中获得掩码字符串。

JFormattedTextField 类有明显的优势,因为它可以在用户输入时验证数据,为用户提供直接的反馈。但是掩码字符串不如正则表达式那么灵活。例如,您可以为美国的 ZIP Code 编写掩码 ##### 或 #####-####,但是不能同时使用这两个掩码。如果一个掩码字符串足以处理一组本地化数据类型,那么从 ResourceBundle 获得掩码字符串就是本技巧的一个很好的用途。(请参阅 参考资料,以找到关于扩展 JFormattedTextField 类的行为的文章。)

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130211/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/374079/viewspace-130211/

[转载]使用正则表达式验证本地化数据相关推荐

  1. 艾伟_转载:ASP.NET MVC数据验证

    关于ASP.NET MVC的验证,用起来很特别,因为MS的封装,使人理解起来很费解.也可能很多人都在Scott Guthrie等人写的一本<ASP.NET MVC 1.0>书中,见过Ner ...

  2. 正则表达式验证代码(字母、数字、Email、网址、电话号码、汉字、身份证号码) (转载)...

    % if request("check")<>"" then astr=request("content") call str( ...

  3. 最万能的登录、注册页。带输入数据的验证。邮箱的正则表达式、正则表达式验证输入的数据

    看别人写的.不是缺胳膊就是少腿.就离谱.因为看不惯别人写的.所以自己写.界面美化可以按照自己的需求自己设计.这里只是提供了简单的前台数据获取以及输入数据的验证.哈哈哈哈哈哈 登录 <!DOCTY ...

  4. jquery正则表达式验证:手机号码

    需求说明: 要求使用正则表达式验证页面文本框输入的数据为手机号码. 代码说明: 这里只介绍正则表达式部分,其他部分的代码不做介绍.如有其它的提示或路径信息可根据需求自行添加. 步骤一:建立一个页面可以 ...

  5. 【转载】C#验证控件的使用方法(RegularExpressionValidator)的使用

    ControlToValidate="要验证的控件名称"  ValidationExpression="验证规则"  ErrorMessage="所要 ...

  6. POSIX正则表达式 验证电子邮件地址

    我们最经常遇到的验证,就是电子邮件地址验证.网站上常见.各种网页脚本也都常用"正则表达式"(regular expression)对我们输入的电子邮件地址进行验证,判断是否合法.有 ...

  7. jquery正则表达式验证:验证全是数字

    需求说明: 前端页面使用正则表达式验证输入框中输入的内容全是数字. 代码说明: 这里只介绍正则表达式,其他部分的代码不做介绍.如果有其他需要自行修改即可. 步骤一:建立一个页面可以是html.jsp等 ...

  8. 手机号判断正则php2019,2019手机号码JS正则表达式验证实例代码

    概念 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的 ...

  9. 正则表达式验证账号代码

    1.正则表达式验证密码账号等: <!DOCTYPE html> <html> <head>     <meta charset="utf-8&quo ...

最新文章

  1. Win7:“找不到该项目”错误解决大法
  2. 再见SpringMVC!linuxkafka安装单机集群
  3. hdu 5037 Frog 贪心 dp
  4. Gradient Boost 算法流程分析
  5. IE6 / IE7 / Firefox 的margin问题解决办法
  6. centos7查看当前端口_Centos7 防火墙开放端口,查看状态,查看开放端口
  7. 葡萄品质无损检测技术的研究进展
  8. 数据结构之哈夫曼编码
  9. Atitit. Dwr 抛出异常error解决方案
  10. CentOS 5.4安装rar
  11. 一分钟实现扫描二维码功能
  12. MODIS数据快速下载方法
  13. php 万能密码,万能用户名和万能密码
  14. windows系统自带工具dxdiag查看电脑信息
  15. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
  16. nodejs+vue+elementui 青少年编程在线考试系统python java php
  17. 驱动开发:断链隐藏驱动程序自身
  18. 制作App,免编程积木式搭建如此之简单
  19. Python操作邮箱发送邮件(网易邮箱)
  20. CANoe.DiVa 操作指南 - 预期响应设置

热门文章

  1. 【设计原则】面向对象的设计原则(六原则一法则)
  2. 测试人员如何做不漏测?这7点就够~
  3. 定义一个复数类Complex,使得下面的代码能够工作:Complex c1(3, 5); //用复数3+5i初始化c1Complex c2 = 4.5; //用实参4.
  4. 【表白系列二】Java实现的表白窗体应用~JFrame实现(雪花飘落)
  5. UBUNTU下AMD显卡驱动安装及切换
  6. 剑灵力士卡刀ahk_用AutoHotkey帮朋友写一份卡刀软件,不清楚力士卡刀数据,帮个忙....
  7. 人工智能、机器学习、深度学习、神经网络概念说明
  8. 男人能成就大事的性格
  9. python读取图片并且转码成base64
  10. 在#haskell@freenode中使用lambdabot