网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  利用java编写html文件分析程序     
  文章作者:未知  文章来源:水木森林  
  查看:74次  录入:管理员--2007-11-17  
 
  ---- 摘要:本文从实践的角度重点阐述java语言中输入流类streamtokenizer在编写html文件分析程序中的应用,并介绍了以字节为单位下载web页面的例程。

一、概述
---- web服务器的核心是对html文件中的各标记(tag)作出正确的分析,一种编程语言的解释程序也是对源文件中的保留字进行分析再做解释的。实际应用中,我们也常常会遇到需要对某一特定类型文件进行关键字分析的情况,比如,需要将某个html文件下载并同时下载与之相关的.gif、.class等文件,此时就要求对html文件中的标记进行分离,找出所需的文件名及目录。在java出现以前,类似工作需要对文件中的每个字符进行分析,从中找出所需部分,不仅编程量大,且易出错。笔者在近期的项目中利用java的输入流类streamtokenizer进行html文件的分析,效果较好。在此,我们要实现从已知的web页面下载html文件,对其进行分析后,下载该页面中包含的html文件(如果在frame中)、图像文件和class(java applet)文件。
二、streamtokenizer类
---- streamtokenizer即令牌化输入流的作用是将一个输入流中变成令牌流。令牌流中的令牌实体有三类:单词(即多字符令牌)、单字符令牌和空白(包括java和c/c++中的说明语句)。
---- streamtokenizer类的构造器为:

streamtokenizer(inputstream in)

---- 该类有一些公有实例变量:ttype、sval和nval ,分别表示令牌类型、当前字符串值和当前数字值。当我们需要取得令牌(即html中的标记)之间的字符时,应访问变量sval。而读向下一个令牌的方法是调用nexttoken()。方法nexttoken()的返回值是int型,共有四种可能的返回:
---- streamtokenizer.tt_number: 表示读到的令牌是数字,数字的值是double型,可以从实例变量nval中读取。

---- streamtokenizer.tt_word: 表示读到的令牌是非数字的单词(其他字符也在其中),单词可以从实例变量sval中读取。

---- streamtokenizer.tt_eol: 表示读到的令牌是行结束符。

---- 如果已读到流的尽头,则nexttoken()返回tt_eof。

---- 开始调用nexttoken()之前,要设置输入流的语法表,以便使分析器辨识不同的字符。whitespacechars(int low, int hi)方法定义没有意义的字符的范围。wordchars(int low, int hi)方法定义构造单词的字符范围。

三、程序实现
---- 1、htmltokenizer类的实现
---- 对某个令牌流进行分析之前,首先应对该令牌流的语法表进行设置,在本例中,即是让程序分出哪个单词是html的标记。下面给出针对我们需要的html标记的令牌流类定义,它是streamtokenizer的子类:

import java.io.*;
import java.lang.string;
class htmltokenizer extends
streamtokenizer {
//定义各标记,这里的标记仅是本例中必须的,
可根据需要自行扩充
static int html_text=-1;
static int html_unknown=-2;
static int html_eof=-3;
static int html_image=-4;
static int html_frame=-5;
static int html_background=-6;
static int html_applet=-7;

boolean outsidetag=true; //判断是否在标记之中

//构造器,定义该令牌流的语法表。
public htmltokenizer(bufferedreader r) {
super(r);
this.resetsyntax(); //重置语法表
this.wordchars(0,255); //令牌范围为全部字符
this.ordinarychar(´< ´); //html标记两边的分割符
this.ordinarychar(´>´);
} //end of constructor

public int nexthtml(){
int token; //令牌
try{
switch(token=this.nexttoken()){
case streamtokenizer.tt_eof:
//如果已读到流的尽头,则返回tt_eof
return html_eof;
case ´< ´: //进入标记字段
outsidetag=false;
return nexthtml();
case ´>´: //出标记字段
outsidetag=true;
return nexthtml();
case streamtokenizer.tt_word:
//若当前令牌为单词,判断是哪个标记
if (allwhite(sval))
return nexthtml(); //过滤其中空格
else if(sval.touppercase().indexof("frame")
!=-1 && !outsidetag) //标记frame
return html_frame;
else if(sval.touppercase().indexof("img")
!=-1 && !outsidetag) //标记img
return html_image;
else if(sval.touppercase().indexof("background")
!=-1 && !outsidetag) //标记background
return html_background;
else if(sval.touppercase().indexof("applet")
!=-1 && !outsidetag) //标记applet
return html_applet;
default:
system.out.println ("unknown tag: "+token);
return html_unknown;
} //end of case
}catch(ioexception e){
system.out.println("error:"+e.getmessage());}
return html_unknown;
} //end of nexthtml

protected boolean allwhite(string s){//过滤所有空格
//实现略
}// end of allwhite

} //end of class

---- 2、html文件分析和下载程序
---- 利用上面自行编写的令牌化流,下面即可对html文件加以分析,并下载所有相关文件。本例中使用以字节为单位下载文件的方法,而非按字符下载,目的是可以下载不同类型的文件(如jpg或class类型的文件)。限于篇幅,仅给出部分实现方法。

//分析html文件
void getit(){
string filename;
string theurl; // html文件的url地址

string tmpfilename;
stringtokenizer st;
string tmp=null;
fileinputstream fin;
inputstreamreader in;
bufferedreader reader=null;
int tagtype;

//变量theurl表示该html页面的位置
if(theurl.touppercase().endswith("html") ||
theurl.touppercase().endswith("htm")){
try{
fin=new fileinputstream(thecurrentpath+filename);
//读入该html文件
in=new inputstreamreader(fin);
reader=new bufferedreader(in);
}catch(filenotfoundexception e){
system.out.println(e.getmessage());}
htmlstream=new htmltokenizer(reader);
//生成类htmltokenizer的实例
//读该令牌流,并做分析
while((tagtype=htmlstream.nexthtml())
!=htmlstream.html_eof){
if(tagtype==htmlstream.html_image){
// 标记< img >
st=new stringtokenizer(htmlstream.sval," ");
//sval即"< img"之后直到下一标记之间的字符
while(st.hasmoretokens()){
tmp=st.nexttoken();
if(tmp.touppercase().trim().startswith("src")){
tmppath=tmp.substring(tmp.indexof(´"´)+1,
tmp.lastindexof(´/´));
//取该图形文件存放的相对目录
tmpfilename=tmppath.substring
(tmppath.indexof(´/´)+1);
//取文件名
catchhtmlfile(theurl,tmppath,tmpfilename);
//下载该文件
} //end of if
} //end of while
} //end of if
else if(tagtype==htmlstream.html_frame){
// 处理同上,取出各框架中的html文件名,分别下载。
} //end of else if
else if(tagtype==htmlstream.html_background){
//略
} //end of the first while
}//end of first if
}//end of getit

//下载html文件,并存放在相应的本地目录下
private void catchhtmlfile(string currenturl,
string thepath,string thefilename){
fileoutputstream fs=null;
inputstream in=null;
dataoutputstream ds=null;
file dir;
int ch;
final int buffer=2048; //输入缓冲区长度
byte buff[]=new byte[buffer];
try{
url=new url(currenturl); //建立与目标文件的连接
uc=url.openconnection();
}catch(malformedurlexception e){
system.out.println("malformed url string!");}
catch(ioexception e){
system.out.println(e.getmessage());}

try{
in=uc.getinputstream();
}catch(ioexception e){
system.out.println(e.getmessage());}
try{
dir=new file(thepath);
if(!dir.exists()) //判断本地目录是否存在
dir.mkdir();
file file=new file(thepath,thefilename);
fs=new fileoutputstream
((thepath+thefilename),false);
}catch(filenotfoundexception e){
system.out.println("file cannot be set
up:"+thepath+thefilename);}
catch(ioexception e){
system.out.println(e.getmessage());}
ds=new dataoutputstream(fs);

try{
while((ch=in.read(buff))!=-1)
//读入字节,并写入本地文件
ds.write(buff,0,ch);
}catch(ioexception e){
system.out.println(e.getmessage());}
try{
in.close();
ds.close();
}catch(ioexception e){
system.out.println
("error in closing i/o stream!");}
}//end of catchhtmlfile

---- 以上方法由笔者在近期项目中测试通过,操作系统为windows nt4,编程工具使用inprise jbuilder3。
摘自《计算机世界》
 
 
上一篇: 利用java 编写手机应用程序    下一篇: 利用java配合bcb 4.0制作cpu特征侦测器
  相关文档
informix j/foundation 11-16
jsr 198最终草案提交 统一ide插件标准 11-17
java 基本语法(二)——变量和常量 11-17
浅谈java中的存储空间类型 11-17
用jms客户端利用空闲的计算机资源 11-17
如何限制用户目录和硬盘使用空间 11-17
课程介绍(4)sl-275 java语言编程 11-16
关于java的classpath详解 11-16
第1个简单java程序 11-17
用filefilter搜索文件 11-17
gettime 方法 11-16
eclipse rcp+spring建胖客户端web程序 11-17
java类中类属性和对象属性的初始化顺序 11-17
用jdom技术将数据库数据写入读出xml文件 11-17
data access application block 概述 11-17
java的垃圾回收机制研究 11-17
确认java拥有足够的内存 11-17
j2ee综合--总结java编程中的经验教训 03-06
关于java的点滴看法 11-17
java核心代码例程之:jniexample.h 11-17
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
厦门(总部):13616026886 福州:0591-87655121
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息