JAVA 数 据 流 的 应 用
---- 常 常 逛WWW 的 人, 一 定 不 会 对 许 多 起 始 页 的 计 数 器 感 到 陌 生。 当 你 每 一 次 光 临 某 些 站 点 的 起 始 页 时, 起 始 页 的 计 数 器 就 会 亲 切 的 告 诉 你, 从 某 年 某 月 某 日 开 始 算 起, 您 是 第 几 个 光 临 这 个 起 始 页 的 人。 你 可 能 知 道 这 是 用CGI 做 的, 后 面 是 什 么 ? 不 是 十 分 清 楚 吧 ! 我 们 这 里 来 分 析 一 下 计 数 器 吧; 如 是 我 写 下 本 文。 当 你 看 完 本 文 之 后 人 你 会 觉 得 计 数 器 是 这 样 的 简 单、 以 后 上Internet 网 时 不 会 觉 得 漂 亮 的 是 多 么 的 复 杂, 而 是 一 个CGI 和 数 据 流 的 杰 作。 看 看 吧 是 多 么 的 平 常 !
import java.net.*;
import java.io.*;
import java.awt.*;
---- 在 这 里 小 程 序 引 入 了 三 类 库。 都 是 标 准 类 库, 为 了 使 用 数 据 流 而 引 入 了java.io.* 类 库; 为 了 使 用URL 引 入 了java.net.* 类 库; 同 时 为 了 在 字 形 与 图 形 引 入 了java.awt.* 类 库。
public class JavaCounter extends java.applet.Applet
这里扩展了Applet,这里的JavaCounter是继承了Applet的属性。
{
Font fn=new Font("TimesRoman",Font.BOLD,24);
设置了显示的字形和使用的确24点字模。
String counter_str,myurl;
String filename;
取得资源Counter。
public void init()
---- 关 键 字public 告 诉java 编 译 器 其 它 对 象 从 类Applet 的 外 部 调 用init 函 数 关 键 字void 告 诉java 编 译 器init 不 向prowser 返 回 任 何 值。
{
filename=getParameter("filename");
if(filename==null) filename="home.txt";
myurl="http://202.115.144.32/cgi-bin/counter.exe?home.txt";
try{
URL serverURL=new URL(myurl);
DataInputStream dis;
dis=new DataInputStream(serverURL.openStream());
counter_str=dis.readLine();
counter_str=dis.readLine();
dis.close();
}
catch(MalformedURLException mfURLe) {}
catch(IOException ioe) {}
}
---- 这 里 我 们 从 网 络 的 远 程 取 得 数 据 文 件 的 过 程。 注: 虽 然 有 此URL 位 置 看 起 来 长, 但 在JAVA 中 基 本 上 是 一 资 源 的 传 输 协 议, 加 上 一 个 资 源 的 名 称。 如 上 面 中 的HTTP 一 样 都 是 典 型 的 传 输 协 议。 通 常 具 有 一 个 或 多 个 结 构。 为 了 处 理 方 便, 在JAVA 中 特 别 为URL 位 置 设 计 了URL 类, 可 以 用 一 个URL 对 象 记 录 下 完 整 的URL 信 息, 这 里 我 们 使 用 的 就 是URL。 同 时 我 们 用 了java.io.*; 中 的 数 据 流 的 程 序 包。 数 据 流 可 以 看 作 是 数 据 的 通 信 途 径。 通 常 是 建 立 一 条 数 据 通 道 后 在 程 序 读 取 时 向 这 个 通 道 发 送 信 号、 远 方 数 据 自 动 送 来 的 过 程 我 们 叫 做" 数 据 流"。 而 本 程 序 主 要 部 分 也 是 这 些。
public void paint(Graphics g)
{
g.setFont(fn);
g.setColor(Color.blue);
g.drawString("庆祝吧!
第"counter_str"位朋友您的到来!",10,50);
}
---- 当 我 们 从 数 据 流 收 到 信 息 后, 就 由Applet 中 的 方 法paint 去 处 理, 并 把 设 好 的 字 形 显 示 于 屏 幕 上。
}
---- 注: 编 好 这 个 程 序 之 后 还 要 一 个CGI 程 序 才 能 发 挥 作 用。 还 是 说 一 下CGI 的 其 本 思 路 吧 ! 我 们 先 打 开"counter.exe?home.txt" 的 记 录 读 出 记 录 加1 并 更 新 数 据 关 闭 记 录。 并 输 出 记 录 通 过 数 据 流 给JAVA 程 序 读 取 的 方 式。 下 面CGI 例 子 是 用C++ 编 的 你 不 妨 试 试 吧 ! ! 同 时 为 了 读 和 应 用 的 方 便 写 下 了CGI 与JAVA 的 全 部 原 程 序。
---- Java 原 程 序 如 下:
import java.net.*;
import java.io.*;
import java.awt.*;
public class JavaCounter extends java.applet.Applet
{
Font fn=new Font("TimesRoman",Font.BOLD,24);
String counter_str,myurl;
String filename;
public void init()
{
filename=getParameter("filename");
if(filename==null) filename="home.txt";
myurl="http://202.115.144.32/
cgi-bin/counter.exe?home.txt";
try{
URL serverURL=new URL(myurl);
DataInputStream dis;
dis=new DataInputStream(serverURL.openStream());
counter_str=dis.readLine();
counter_str=dis.readLine();
dis.close();
}
catch(MalformedURLException mfURLe)
{}
catch(IOException ioe)
{}
}
public void paint(Graphics g)
{
g.setFont(fn);
g.setColor(Color.blue);
g.drawString(counter_str,10,50);
}
}
---- CGI 程 序 代 码 如 下:
#include < windows.h >
#include < stdio.h >
int SplitArgs (char *str, char *argv[]);
int PASCAL WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nShow)
{
int argc;
char *argv[32]; // Max 32 command line arg
long num;
FILE *fp;
argc = SplitArgs(lpszCmdLine, argv);
// Split command line args
puts("Content-type: text/plain\n");
// NOTE: blank line here
if(argc< =1)
{printf("!!!Too less Parameter!!!");
printf("\n用法为在counter.exe?
后加上数据文件名");
return(1);
}
fp=fopen(argv[1],"r");
fscanf(fp,"%ld",&num);
num++;
printf("\n%ld",num);
fclose(fp);
fp=fopen(argv[1],"w");
fprintf(fp,"%ld",num);
fclose(fp);
return(0);
}
int SplitArgs (char *str, char *argv[])
{
int argc;
char *cp;
static char safe_copy[256];
// Single threaded, this is OK
char appname[256];
GetModuleFileName(NULL, appname, 256);
// Get app filename
memset(safe_copy, 0, sizeof(safe_copy));
// Must clear old stuff...
strcpy(safe_copy, appname); // VC++ 2.0
strcat(safe_copy, " ");
strcat(safe_copy, str);
argc = 0;
cp = safe_copy;
while (*cp) // Stop at null character
{
while(*cp && isspace (*cp))
// Scan past white or to end
cp += 1;
if(*cp) // On next token or at end
argv[argc++] = cp; // Next token: ptr and bump
while(*cp && !isspace (*cp)) // Scan to white or end
cp += 1;
*cp++ = '\0'; // Terminate this token
}
return (argc);
}
---- 注: 一 定 要 另 加 一 个 文 本 文 件 名 要 与JAVA 中 文 本 文 件 同 名, 还 需 要 在 文 本 文 件 中 写 一 个 字 符"1" 就 好 了。 与 您 的CGI 程 序 放 在 同 一 目 录 中。