十一
12
2010
最近突然对股票很感兴趣,在学习的过程中就萌生了一个想法:“如果有一个股票短信查询系统该多好啊,发送股票代码到指定的号码,然后就能立马收到该股票实时信息”。经过一些技术调研之后,发现借助移动的139手机邮箱就可以实现该功能,一切都是免费的!
一、原理:
- 移动139邮箱提供了“用短信发邮件的功能”,使用方式:发送短信 “邮件地址[空格或#]邮件主题[空格或#]邮件正文” 到10658139。
利用此功能,我们就可以用短信,将想要查询的股票代码发送到指定的邮箱 “getstock@126.com ”中。
- 写程序,不断读取邮箱 “getstock@126.com ”中的邮件,得到股票代码和发件人邮箱地址。
- 根据股票代码,利用新浪股票查询接口,获取实时股票数据。
- 将股票数据,发送到第2步获得的发件人的邮箱中(移动会把139邮箱的邮件,自动以短信形式发送到用户手机上)。
二、使用方式:
- 开通139邮箱,并且在邮箱的设置中开启“邮件到达通知”功能,手机接收方式最好选择长短信。
- 发送短信 “getstock@126.com 600050” 到 10658139 (后台服务已开启,欢迎大家测试)
注:600050是股票代码
三、延伸:
其实,利用此原理还可以做好多有趣的事情,例如发短信获取百科数据、发短信远程操作电脑… 主要看大家的想象力了。
四、源码下载:
StockSMS.zip 代码未整理,将就查看
五、相关链接
- 139手机邮箱短信操作指令汇总
- 新浪股票查询接口
原文地址:http://www.hijava.org/code/build-stock-sms-query-system-use-139-mail
1 comment | tags: http, mail | posted in 编程实践
九
18
2010
1、Cookie文件的实质
Cookie实际上是Web服务端与客户端(典型的是浏览器)交互时彼此传递的一部分内容,内容可以是任意的,但要在允许的长度范围之内。客户端会将它保存在本地机器上(如IE便会保存在本地的一个txt文件中),由客户端程序对其进行管理,过期的Cookie会自动删除。每当客户端访问某个域下某个目录中的网页时,便会将保存在本地并且属于那个域下对应目录的有效Cookie信息附在网页请求的头部信息当中一并发送给服务端。
2、Cookie文件的保存位置
不同的客户端,其Cookie的保存方式、保存位置各不相同,这里只说一下Windows系统中IE的Cookie文件保存位置。
在Windows 2000/XP系统中,Cookie默认保存在C:\Documents and Settings\\Cookies\目录下(此处的为你登录系统时使用的用户名,在开始->运行中输入cookies便可打开该目录),命名规则为@.txt。
与2000/XP不同的是,在Windows 95/98/ME系统中Cookie文件默认是保存在C:\Windows\Cookies\目录下的。
3、Cookie文件的格式
IE的Cookie文件实际上就是一个txt文本文件,只不过换行符标记为Unix换行标记(0x0A),由于记事本对Unix换行标记不兼容,打开后内容全在一行看起来不方便,我们可以用EditPlus或UltraEdit-32打开,打开之后,会看到形式如下的内容:
name
value
domain/
1600
1263382784
30020896
452781968
30020892
*
每一行的内容说明:
英文说明:
Line Summary
1 The Variable Name
2 The Value for the Variable
3 The Website of the Cookie’s Owner
4 Optional Flags
5 The Most Significant Integer for Expired Time, in FILETIME Format
6 The Least Significant Integer for Expired Time, in FILETIME Format
7 The Most Significant Integer for Creation Time, in FILETIME Format
8 The Least Significant Integer for Creation Time, in FILETIME Format
9 The Cookie Record Delimiter (a * character)
中文说明:
第一行 Cookie变量名
第二行 Cookie变量值
第三行 该Cookie变量所属域,形如csdn.net/、blog.csdn.net/或blog.csdn.net/lixianlin/
第四行 可选标志
第五行 该Cookie过期时间(FILETIME格式)的高位整数
第六行 该Cookie过期时间(FILETIME格式)的低位整数
第七行 该Cookie创建时间(FILETIME格式)的高位整数
第八行 该Cookie创建时间(FILETIME格式)的低位整数
第九行 Cookie记录分隔符(为一个星号* )
补充一下,第三行中Cookie变量所属域,如csdn.net/,它是一个根域,也就是一级域,表示该Cookie变量在该根域下的所有目录中的网页都有效,不管访问该域下的哪个目录中的网页,浏览器都会将该Cookie信息附在网页头部信息当中发送给服务端;blog.csdn.net/,是一个二级域,表示该Cookie只对blog这个二级域下目录中的网页有效;blog.csdn.net/lixianlin/,是一个二级域下的目录,只有访问blog这个二级域下lixianlin这个目录中的网页时,才会把该Cookie信息附在请求头部信息当中发送给服务端。需要指出的是csdn.net/和www.csdn.net/并不相同,前者是根域,后者是一个二级域,只是人们习惯了www这样的形式,所以大多数的网站首页都用http://www.xxx.com/这样的二级域来访问。
附FILETIME格式定义:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
转自:http://blog.csdn.net/lixianlin/archive/2008/07/30/2738229.aspx
1 comment | posted in 编程实践
九
4
2010
1
2
3
4
5
6
7
| @echo off & setlocal EnableDelayedExpansion
set LIB_CP=
for /r . %%i in ("lib\*.jar") do (
set LIB_CP=!LIB_CP!;%%i
)
java -cp .\conf%LIB_CP%
exporting.gui.ExportWizard |
可以将某个目录下的所有JAR文件配置到环境变量中,很强大的一段脚本~
no comments | tags: bat, classpath | posted in 编程实践
八
17
2010
注意:建议使用org.apache.tools.zip.*包下相关类,否则可能会出现中文乱码问题。
参考:java 实现zip与unzip
no comments | tags: java, zip | posted in 编程实践
八
5
2010
对于简单的对象,只要实现Cloneable接口,并且重写Object类的clone()方法即可。对于复杂的对象,必需将其中的复杂成员变量也进行clone,实现起来太繁琐。这里有一种简便方法,先将对象序列化到内存,然后再其反序列化。主要代码如下所示:
参照:java clone方法使用详解
1 comment | tags: java | posted in 编程实践
八
3
2010
最近老想看电影,把豆瓣和迅雷翻了个底朝天也没找到几个合适的,主要是这些网站都不提供按照评分排序的功能。于是利用周末的时间,写了个爬虫,先爬取豆瓣上的电影,然后再按照用户评分从高到低排序输出。最后会生成一个网页,如下图所示:

底层用到了之前介绍的HttpBot,生成结果网页用到了volecity,获取电影信息(评分、评价数、上映时间…)用的是正则表达式,其它就没什么特别的了。
程序还有很多不足,日后慢慢完善了…
1 comment | tags: douban, http | posted in 编程实践
八
1
2010
HttpBot 是对 java.net.HttpURLConnection类的简单封装,可以方便的获取网页内容,并且自动管理session,自动处理301重定向等。虽然不能像HttpClient那样强大,支持完整的Http协议,但却非常地灵活,可以满足我目前所有的相关需求。
获取Google首页Html代码仅需要如下两行代码即可:
1
2
| HttpBot httpBot=new HttpBot();
String html=httpBot.doGet("http://www.google.com"); |
感兴趣的可以到 http://hijava.googlecode.com/svn/HttpBot (SVN地址) 下载最新的源码。目前还太简单(200行代码),不过仍在不断维护中。
HttpBot部分源代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
| package org.hijava.httpbot;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* Http网络爬虫类
*
* @author yava
*/
public class HttpBot {
private Map cookieMap;
private String userAgent;
private String encoding;
private String host;
private String referer;
private int responseCode;
private static final String separator = System.getProperty("line.separator");
private static final String GET="GET";
private static final String POST="POST";
public HttpBot() {
this.userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";
this.encoding = "UTF-8";
cookieMap=new HashMap();
}
public HttpBot(String host,String referer){
this();
this.host=host;
this.referer=referer;
}
/**
* 以GET方式发送请求,返回页面html代码
* @param urlStr
* @return
*/
public String doGet(String urlStr) {
HttpURLConnection http=getConnection(urlStr,HttpBot.GET);
String content="";
try {
http.connect();
processCookie(http);
this.referer=urlStr;
this.responseCode=http.getResponseCode();
if(this.responseCode==302){
String location=http.getHeaderField("Location");
return doGet(location);
}
InputStream is=http.getInputStream();
content=getContent(is);
is.close();
http.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
/**
* 以Post方式发送请求,返回页面html代码
* @param urlStr
* @param paramMap 请求参数
* @return
*/
public String doPost(String urlStr,Map paramMap){
HttpURLConnection http=getConnection(urlStr,HttpBot.POST);
http.setDoOutput(true);
String content="";
try {
OutputStream os = http.getOutputStream();
os.write(getParamBytes(paramMap));
http.connect();
processCookie(http);
this.referer=urlStr;
this.responseCode=http.getResponseCode();
if(this.responseCode==302){
String location=http.getHeaderField("Location");
return doGet(location);
}
InputStream is=http.getInputStream();
content=getContent(is);
is.close();
http.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
/**
* 从输入流获取网页内容
* @param is
* @return
*/
private String getContent(InputStream is){
StringBuilder builder = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is,encoding));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line).append(separator);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
private HttpURLConnection getConnection(String urlStr,String reqMethod){
HttpURLConnection http=null;
try {
URL url = new URL(urlStr);
http = (HttpURLConnection) url.openConnection();
http.setRequestProperty("User-Agent", this.userAgent);
http.setRequestProperty("Host", this.host);
http.setRequestProperty("Cookie", this.getCookie());
http.setRequestProperty("Referer", this.referer);
http.setRequestMethod(reqMethod);
http.setInstanceFollowRedirects(false);
} catch (IOException e) {
e.printStackTrace();
}
return http;
}
/**
* 处理cookie
* @param http
*/
private void processCookie(HttpURLConnection http){
String key = null;
for (int i = 1; (key = http.getHeaderFieldKey(i)) != null; i++) {
if (key.equalsIgnoreCase("set-cookie")) {
String cookie = null;
cookie = http.getHeaderField(i);
int i1=cookie.indexOf("=");
int i2=cookie.indexOf(";");
if(i1!=-1&&i2!=-1){
String _value=cookie.substring(i1+1, i2);
if("EXPIRED".equalsIgnoreCase(_value)){
continue;
}
String _key=cookie.substring(0, i1);
cookieMap.put(_key, _value);
}
}
}
}
/**
* 获取cookie
* @return
*/
public String getCookie(){
String cookie="";
for(Map.Entry entry:cookieMap.entrySet()){
cookie=cookie+entry.getKey()+"="+entry.getValue()+";";
}
return cookie;
}
private byte[] getParamBytes(Map paramMap){
String paramStr="";
for(Map.Entry entry:paramMap.entrySet()){
String value="";
try {
value=URLEncoder.encode(entry.getValue(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
paramStr=paramStr+entry.getKey()+"="+value+"&";
}
return paramStr.getBytes();
}
} |
1 comment | tags: http, httpbot | posted in 编程实践
五
2
2010
3 comments | tags: google, java, rss | posted in 编程实践
二
25
2010
今天工作中遇到一个问题,虽然在Employee中重写了equals方法,但是往HashSet中存放Employee对象的时候还是出现了重复值。
于是查看了JDK源码,发现HashSet竟然是借助HashMap来实现的,利用HashMap中Key的唯一性,来保证HashSet中不出现重复值。具体参见代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<E,Object>();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
} |
由此可见,HashSet中的元素实际上是作为HashMap中的Key存放在HashMap中的。下面是HashMap类中的put方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} |
从这段代码中可以看出,HashMap中的Key是根据对象的hashCode() 和 euqals()来判断是否唯一的。
结论:为了保证HashSet中的对象不会出现重复值,在被存放元素的类中必须要重写hashCode()和equals()这两个方法。
no comments | tags: java | posted in 编程实践
二
6
2010
前一段时间写过的一个集合排序的方法,可以按照集合中存放Bean的任意属性进行排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| /**
* 按照指定属性,对List集合进行排序。
*
* @param list bean集合
* @param sortBy 要进行排序的bean中的属性
* @param sort 升序或降序
*/
public static <T> void sort(List<T> list, final String sortBy,final String sort) {
if (list == null || sortBy == null ||sortBy.equals("")|| list.isEmpty())
return;
Collections.sort(list, new Comparator<T>() {
@SuppressWarnings("unchecked")
public int compare(T t1, T t2) {
Object o1 = null;
Object o2 = null;
try {
o1 = ReflexUtil.getObjFieldValue(t1, sortBy);
o2 = ReflexUtil.getObjFieldValue(t2, sortBy);
} catch (Exception e) {
e.printStackTrace();
}
int result = 0;
if(o1==null){
result=-1;
}
else if(o2==null){
result=1;
}
//字符串按照拼音排序
else if (o1 instanceof String) {
result = Collator.getInstance(Locale.CHINA).compare(o1, o2);
} else {
result = ((Comparable) o1).compareTo(o2);
}
if(DESC.equalsIgnoreCase(sort)){
result=0-result;
}
return result;
}
});
} |
注:ReflexUtil.getObjFieldValue(t1, sortBy) 用反射技术获取对象t1中sortBy属性的值。
no comments | tags: java | posted in 编程实践