[java] 汇率换算器实现(2)

 

[java] 汇率换算器实现(2)

1 系列文章地址

2 前言

在上篇文章中, 我们实现了汇率换算器的最简单的版本, 实现了:

  • 帮助信息的提示
  • 汇率表的输入
  • 错误输入的处理
  • 汇率计算的输入
  • 汇率计算结果的输出

不同类之间的关系图如下(不是严格按照uml规则绘制的):

在接下来的内容中主要介绍如何实现汇率表的实时更新.

3 获取实时汇率信息

想要获取汇率的实时信息, 很容易想到的方法就是从一个网页中提取相应的汇率信息, 填充到当前的汇率表内. 接着自然想要, 使用java进行network programming, 可以借用java.net库.

3.1 获取网页内容

class Rate {
// 从网站:http://www.usd-cny.com/中获取最新的汇率信息
final static String webSite = "http://www.usd-cny.com/"; // 利用hashtable对不同货币之间的利率进行存储
// key: $from+$to, value: $rate
private static Hashtable rateTable = new Hashtable(); // 获取网页内容
public static void update() throws Exception {
URL hp = new URL(webSite);
URLConnection hpCon = hp.openConnection(); System.out.println("== Content ==");
InputStream input = (InputStream)hpCon.getInputStream();
BufferedReader br = new BufferedReader(new
InputStreamReader(input, "gb2312")); String str = null;
while (( str = br.readLine() ) != null) {
System.out.println(str);
}
input.close();
}
}

接下来要干的活就是从获得的网页内容中提取出汇率表信息了. 网页上显示的格式如下:

3.2 提取web表单

为了存储表单中提取的信息, 建立了一个新类: class RateInfo

class RateInfo {
String to;
// [0]: 现汇买入价 [1]: 现钞买入价
// [2]: 卖出价 [3]: 中间价 [4]: 基准价
Double price[] = new Double[5];
}

具体的实现可以通过两种方式:

  • 正则表达示匹配
  • 借用现有的库, jsoup

该文主要实现了第一种方式, 这里再次说明一下,在后续的文章中会介绍关于jsoup的使用。

4 正则表达示匹配获取表单信息

首先让我们来观察一下需要处理的网页的source code.

<TABLE BORDER CELLSPACING=0 BORDERCOLOR="#CCCCCC" CELLPADDING=0 WIDTH=777 align="center" height="113">
<TR bgcolor="#E1FDE8">
<TD WIDTH="121" HEIGHT=28 bgcolor="#E1FDE8">
<DIV ALIGN="center"><b><font color="#000000"><font lang="ZH-CN">货币名称</font></font>
</b> </TD>
<TD WIDTH="133" HEIGHT=21> <DIV ALIGN="center"><b><font color="#000000"><font lang="ZH-CN">现汇买入价</font></font>
</b> </TD>
<TD WIDTH="137" HEIGHT=21> <DIV ALIGN="center"><b><font color="#000000"><font lang="ZH-CN">现钞买入价</font></font>
</b> </TD>
<TD WIDTH="132"><div align="center"><b><font color="#000000"><font lang="ZH-CN">卖出价</font></font></b></div></TD>
<TD WIDTH="130"><div align="center"><b><font color="#000000">中间价</font></b></div></TD>
<TD WIDTH="133" HEIGHT=21> <DIV ALIGN="center"><b><font color="#000000">基准价</font>
</b> </TD>
</TR> <TR bgcolor="#FFFFFF">
<TD HEIGHT=28 valign="middle" bgcolor="#FFFFFF">
<div align="center"><!--?hbmc=美元&topic="--><a href="http://www.usd-cny.com/usd-rmb.htm">美元 USD</a></div></TD>
<TD HEIGHT=15 align="center" valign="middle"><div align="right">621.8700&nbsp;</div></TD>
<TD HEIGHT=15 align="center" valign="middle"><div align="right">616.8900&nbsp;</div></TD>
<TD align="center" valign="middle"><div align="right">624.3700&nbsp;</div></TD>
<TD align="center" valign="middle"><div align="right">623.1200&nbsp;</div></TD>
<TD HEIGHT=15 align="center" valign="middle"><div align="right">615.5700&nbsp;</div></TD>
</TR>

分析发现, 汇率表由大写的TABLE包括起来, 每一行由TR包围, 每一项由TD包围. 因此, 正则表达式为:

  • <TABLE: means enter the table
  • </TABLE: means quit the table
  • <TR: means enter a row
  • </TR: means quit a rwo
  • <TD && href: means first col
  • <TD && ~href: means other cols
  • <TD.*<a href.*?>\(.*?\)</a>: now "\1" means "美元 USD"
  • <TD.*<div.*?>\(.*?\)</d: now \1 meas the rates

对于上述字符的识别可以用以下方式进行实现:

str.startwith(token), where token = "<TABLE" or "</TABLE" or "<TR" or "</TR"
str.startwith("<TD") && str.indexOf("href) != -1, to recognise the first col
str.startwith("<TD") && str.indexOf("href) == -1, to recognise the other cols to extract the unit of the money
import java.util.regex.*;
String patt = "<TD.*<a href.*?>\\(.*?\\)</a>"
Pattern r = Pattern.compile(patt);
Matcher m = r.matcher(str);
m.group(1); // is the result, such as "美元 USD" 用类似的方法可以获得rates

然后编写代码进行实现, 具体实现思路如下:

  • 实现html源代码中关于汇率表的相关内容行的识别
  • 然后, 从特定的行中提取出相应的汇率信息
class Rate {
// 从网站:http://www.usd-cny.com/中获取最新的汇率信息
final static String webSite = "http://www.usd-cny.com/"; // 利用hashtable对不同货币之间的利率进行存储
// key: $from+$to, value: $rate
private static Hashtable rateTable = new Hashtable(); // 从网上自动更新汇率信息
// 只将前16个具有完整汇率信息的内容进行存储
public static void update() throws Exception {
URL hp = new URL(webSite);
URLConnection hpCon = hp.openConnection(); System.out.println("== Content ==");
InputStream input = (InputStream)hpCon.getInputStream();
BufferedReader br = new BufferedReader(new
InputStreamReader(input, "gb2312")); String str = null;
boolean inTable = false;
int nRows = 0;
String matchStr = null;
while (( str = br.readLine() ) != null) {
str = str.trim(); // 判断是否进入汇率表的势力范围内部
if (str.startsWith("<TABLE")) {
inTable = true;
continue;
} if (str.startsWith("</TABLE")) {
break;
} if (inTable == false)
continue; if (str.startsWith("<TR")) {
nRows += 1;
// 忽略第一行的标题
if (nRows == 1) continue; // 汇率表的读取只到港币
if (nRows == RateInfo.NKINDS+2) break; // 获得第一列的完整代码
str = br.readLine().trim();
str = str + br.readLine().trim(); // 获取币种缩写
String patt = "<TD.*<a href.*?>(.*)</a>";
Pattern r = Pattern.compile(patt);
Matcher m = r.matcher(str);
// matchStr = m.group(1);
// 将汉字与缩写进行分离
// matchStr = (matchStr.split())[1];
if (m.find()) {
matchStr = m.group(1);
matchStr = (matchStr.split(" "))[1];
System.out.println(matchStr);
} else {
System.out.println("No Match");
} for (int i = 0; i < RateInfo.NELEM; i++) {
str = br.readLine();
String pattE = "<TD.*>(.*?)&nbsp;</div>";
r = Pattern.compile(pattE);
m = r.matcher(str);
if (m.find())
System.out.println(m.group(1));
else
System.out.println("No Match");
}
}
}
input.close();
} // 设置不同货币之间的利率
// 1 $from * $rate = 1 $to
public static void setRate(String from, String to, double rate) {
rateTable.put(from+to, new Double(rate));
} public static Double getRate(String from, String to) {
return 615.65;
// return (Double) rateTable.get(from + to);
} // 将一定量的货币$m, 转变成单位为$to的货币量
// return: 相应的货币值
public static Money exchangeRate(Money m, String to) {
if (m.unit.equals(to)) return new Money(m);
Double rate = getRate(m.unit, to); if (rate == null) {
throw new IllegalArgumentException();
} return new Money(m.amount*rate.doubleValue(), to);
}
}

5 总结

该文实现了利用正则表达式获取html表单信息. 但是, 该方法主要有的不足是: 具有太明显的目的性, 根据具体html代码的特征实现相应的匹配. 为了实现更普遍的方法, 应该对该匹配规则进行改进, 下一篇文章种将对该方法进行进一步的改进.

Date: 2014-05-07 Wed

Author: Zhong Xiewei

Org version 7.8.11 with Emacs version 24

Validate XHTML 1.0

[java] 汇率换算器实现(2)的更多相关文章

  1. [java] 汇率换算器实现(3)

    [java] 汇率换算器实现(3) // */ // ]]>   [java] 汇率换算器实现(3) Table of Contents 1 系列文章地址 2 前言 3 提取简单表单信息 3.1 ...

  2. [java] 汇率换算器实现-插曲1-正则表达式(1)

    [java] 汇率换算器实现-插曲1-正则表达式(1) // */ // ]]> // */ // ]]>   [java] 汇率换算器实现-插曲1-正则表达式(1) Table of C ...

  3. [java] 汇率换算器实现(1)

    [java] 汇率换算器实现(1) // */ // ]]>   [java] 汇率换算器实现(1) Table of Contents 1 问题描述 2 类设计 3 初步实现 3.1 建立项目 ...

  4. [java] 更好的书写equals方法-汇率换算器的实现(4)

    [java] 更好的书写equals方法-汇率换算器的实现(4) // */ // ]]>   [java] 更好的书写equals方法-汇率换算器的实现(4) Table of Content ...

  5. [java] 注释以及javadoc使用简介-汇率换算器的实现-插曲3

    [java] 注释以及javadoc使用简介-汇率换算器的实现-插曲3 // */ // ]]>   [java] 注释以及javadoc使用简介-汇率换算器的实现-插曲3 Table of C ...

  6. [java] jsoup使用简介-汇率换算器实现-插曲2

    [java] jsoup使用简介-汇率换算器实现-插曲2 // */ // ]]>   [java] jsoup使用简介-汇率换算器实现-插曲2 Table of Contents 1 系列文章 ...

  7. 【菜鸟学Python】案例一:汇率换算

    汇率换算V1.0 案例描述: 设计一个汇率换算器程序,其功能是将外币换算成人民币,或者相反 案例分析: 分析问题:分析问题的计算部分: 确定问题:将问题划分为输入.处理及输出部分: 设计算法:计算部分 ...

  8. 汇率换算自然语言理解功能JAVA DEMO

    >>>>>>>>>>>>>>>>>>>>>>>> 欢迎转 ...

  9. 万航单位换算器 V1.0 绿色版

    软件名称: 万航单位换算器软件语言: 简体中文授权方式: 免费软件运行环境: Win 32位/64位软件大小: 347KB图片预览: 软件简介:万航单位换算器是一个可以随意转换单位的绿色软件,这个软件 ...

随机推荐

  1. Web应用数据库配置参数读取方法之一

    jsp页面: <% //从配置中获取数据库驱动 String driver=application.getInitParameter("driver"); //从数据库中得到 ...

  2. Linux环境下中文字体乱码处理办法

    项目中包含了一项生成JPG图片的功能,该功能需要使用JAVA的Graphics2D动态生成图片中的文字,原来在Windows平台中没有发现问题,但是迁移至Linux平台后发现生成的中文变成了乱码. 百 ...

  3. Ubuntu NFSserver 简易安装及使用

    服务器端(ip:192.168.1.100): sudo apt-get install nfs-kernel-server #安装nfs 客户端(ip:192.168.1.110): sudo ap ...

  4. nginx.conf各参数的意义

    搬运+翻译至 http://qiita.com/syou007/items/3e2d410bbe65a364b603 /etc/nginx/nginx.conf 记录各个参数的意义 user user ...

  5. LiveCD DSET日志收集

      DELL的LiveCD是一张PE光盘,最新版本7.1是基于CentOS 6.2系统的. 工具下载地址: http://downloads.dell.com/FOLDER01960516M/1/SL ...

  6. 【原】react-router项目实战

    摘要: react-router相对于flux和redux来说,比较好容易理解一点和容易入门一点.这个是根据我之前的一个项目,然后我用react+react-router+webpack重新写的. 不 ...

  7. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.4,增加系统设置、最近联系人、群功能(源码)

    自从上次版本(GG叽叽V3.2,增加离线消息.离线文件功能)发布后,我个人觉得主要的大功能都实现得差不多了,接下来的几个版本将不断优化GG的细节,提高其可用性.这次版本更新的内容主要是为GG增加了系统 ...

  8. Linux date命令

    命令概述 date命令可以用来设置和显示系统当前时间,特别是在有一些Shell命令里面用到date命令来做日期的不同的显示,所以该命令也是非常需要掌握的一个命令. 语法 date [OPTION].. ...

  9. 面向对象架构模式之:领域模型(Domain Model)

    一:面向对象设计中最简单的部分与最难的部分 如果说事务脚本是 面向过程 的,那么领域模型就是 面向对象 的.面向对象的一个很重要的点就是:“把事情交给最适合的类去做”,即:“你得在一个个领域类之间跳转 ...

  10. 如何为编程爱好者设计一款好玩的智能硬件(十)——无线2.4G通信模块研究·一篇说完

    六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...