[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. Getting Started with WebRTC [note]

    Getting Started with WebRTC 原文 RTCPeerConnection 1.caller和callee互相发现彼此 2.并且交换capabilities信息 3.初始化ses ...

  2. PPC MPC85xx e500学习笔记

    powerpc的内存体系结构 E500内核中包含内存管理单元MMU,其包含两个查找表(TLB0 Transaction Lookside Buffer)和TLB1来实现虚拟地址和物理地址的转化,其中T ...

  3. ieee80211w

    80211w概述 1, WLAN网络在设计的时候就容易遭受各种类型的Denial of Service(DOS)攻击, a, 射频干扰(RF jamming) b, Spoofed Disconnec ...

  4. Mac环境下svn的使用

    在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境.在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还 ...

  5. 黑马程序员——HTML表格布局

    ---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net ...

  6. anyncTask的3个参数

    AnyncTask异步处理数据并将数据应用到视图的操作场合 一  其中包含这几个方法 1 onPreExcute() 初始化控件,例如进度条2 doInBackground() 具体的执行动作请求数据 ...

  7. PL/SQL Developer登入时候报ORA-12638: 身份证明检索失败的解决办法

    找到安装目录:C:/oracle/product/10.2.0/db_1/NETWORK/ADMIN 打开sqlnet.ora 在里面找到 SQLNET.AUTHENTICATION_SERVICES ...

  8. 我的ORM之二--添加

    我的ORM索引 添加的语法: var 影响行数 = dbr.表.Insert(实体).Execute(); 实体类型 1. 任何C#类. 如:public class Entity{   public ...

  9. 手机淘宝UWP

    各位园主好! bug 走势: 哪天bug 足够少,哪天就可以发布了  :) 2015/10/23: 49 2015/10/26: 40 2015/10/27: 36 2015/10/28: 30 20 ...

  10. Win10 UWP应用发布流程

    简介 Win10 UWP应用作为和Win8.1 UAP应用不同的一种新应用形式,其上传至Windows应用商店的流程也有了一些改变. 这篇博文记录了我们发布一款Win10 UWP应用的基本流程,希望为 ...