国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

利用Java編寫HTML文件分析程序

2019-11-18 14:59:39
字體:
來源:轉載
供稿:網友

  ---- 摘要:本文從實踐的角度重點闡述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。
摘自《計算機世界》

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 桃源县| 汕尾市| 二连浩特市| 凤阳县| 黎平县| 元氏县| 泸水县| 双鸭山市| 柳江县| 贡觉县| 凤山市| 芒康县| 尚义县| 莆田市| 镇远县| 阿勒泰市| 巴青县| 秦安县| 城市| 龙川县| 雷波县| 昌平区| 禄丰县| 县级市| 大港区| 安新县| 诏安县| 册亨县| 涟源市| 武城县| 弋阳县| 佳木斯市| 东至县| 崇义县| 梨树县| 疏勒县| 泰兴市| 文登市| 盐津县| 华安县| 兴国县|