利用JAVA向垃圾电子邮件宣战
2008-01-05 09:45:07 来源:WEB开发网核心提示:摘 要:计算机技术给我们的日常生活带来了很多便利:来自生产线 的产品、高效的通信以及大量易于访问的信息,然而它同时也带来了垃圾电子邮件,利用JAVA向垃圾电子邮件宣战,幸运的是, 我们已经有办法对付它,以结束程序,这种解决方案很简单,本文将对java类库的I/O包以及建立在其上的“流”模型进行深入的讨 论,包括:它是如
摘 要:计算机技术给我们的日常生活带来了很多便利:来自生产线 的产品、高效的通信以及大量易于访问的信息,然而它同时也带来了垃圾电子邮件。幸运的是, 我们已经有办法对付它。本文将对java类库的I/O包以及建立在其上的“流”模型进行深入的讨 论,包括:它是如何工作的,Java1.0.2和Java1.1在I/O实现方面的差别,以及如何利用这些知 识建立一个垃圾电子邮件“过滤器”。
“足不出户,也能至富”
“神奇的饮食,一周减肥20磅”
“热情的XXX宝贝想见你”
有时,我们会收到很多不受欢迎的 电子邮件,这些邮件往往令人不快。那些还没有受垃圾电子邮件之苦的幸运者也应该意识到这 是一个现实的问题。这里我们将介绍一种利用JAVA控制垃圾电子邮件的方法。
监视敌人
我们无法逃避垃圾电子邮件,只能 尽量减少它对我们生活的侵扰。最好,也是最有效的方法是阻止人们给我们发不受欢迎的电子 邮件。我们必须在看到垃圾电子邮件之前消除它,那么如何实现呢?
一种行之有效的方法是检查电子邮件的内容,然后决定是否保留它。其实,我们在阅读电子邮件时就是这样做的:我们一个接一个字符、一行接一行地读电子邮件,搜索我们熟悉地单词,假如其中包括单词“Java”,我们便保留它,假如包括“MakeMoneyFast”,我们便将它扔到垃圾桶里。能否编制一个计算机程序来帮助我们更有效地工作呢?
战术评估
下面,我们讨论Java类库I/O包中 的类。Java类库的输入输出类基于一种简单但强大的模型:“流”(Streams)。
在“流”模型中,信 息从一点“流”到另一点,就象在河流或者管道中一样。在“流”中的任何一点,观察者看到信息一 点一点地顺序流过。这种模型适合现实世界中很多类型的信息,比如来自计算机键盘的键 码(Keycodes)、来自声音文件的声音数据、来自文本文件的一行接一行的文本等都是信息流。
图1“流”中信息从一点传到另一点
“流”中的一个重 要工具便是“过滤器”(Filters)。“过滤器”从“流”的“上游”获取信息,用某种方式过滤或者处理 后,发送到“流”的“下游”。“流”模型功能强大的要害是可以用一些非常简单的、独立的“过滤器” 串成一个功能强大的复合“过滤器”。
图2“过滤器”中断处理信息流
图3级联“过滤器”
Java类库将“流”分为两类──输 入和输出,这种区分在理论上是不必要的,但是在实际应用中却是有用的。输入“流”的最初来源 是某一设备或者文件,它将数据从设备或文件输入到程序中,输入“流”在处理中一般是要过滤 的。输出“流”的最终目标也是某一设备或者文件,它将数据从程序输出到设备或文件中,输入“ 流”在处理中一般也是要过滤的。
有两个原因使我们将Java类库中 的“流”类应用到垃圾电子邮件问题的解决方案中:
可以很轻易地将电子邮件看做是一个接一个字符、一行接一行进入到计算机的。
当电子邮件进入计算机时,我们要一个接一个字符、一行接一行地检查是否与我们指定的模板匹配。
兵工厂──“流”类具体介绍
Java1.1说明书中描述了两种基 本相同的输入和输出类集,一种是面向字节的,另一种是面向字符的。面向字节“流”类与在Java 1.0.2中实现的只有微小的差别,而面向字符“流”类是在Java1.1版本中最新实现的。
本文中我们讨论面向字节的“流”类,这样做有两个原因。首先,对那些没有使用Java1.1的人也可以利用这份材料;其次,我们可以指出Java1.0.2中类库中出现、在Java1.1中已经修正的一些错误。
上面已经提过,“流”可以分为两类:输入“流”和输出“流”。在Java中,所有面向字节的输入“流”类都是抽象类InputStream的子类,InputStream定义了所有输入“流”类必须提供的一套基本方法(Mothods)。同样,所有面向字节的输出“流”类都是抽象类OutputStream的子类,OutputStream定义了所有输出“流”类必须提供的一套基本方法(Mothods)。
通用输入“流”类方法
以下是对所有输入“流”通用的方 法,每个方法说明之后列出了方法能执行的任务。
publicint read()throws IOException
从输入“流”读一个 字节并且返回此字节。
假如已经 到了输入“流”的结尾,则返回-1。
假如必要,阻塞(或等待)直到数据可用。
当读操作时发生错误,则抛 出IOException异常。
publicint read(byte[]rgb) throws IOException
从输入“ 流”读一字节序列并且置于指定的数组中。
返回所读的字节数。
假如已经到了输入“流”的结尾, 则返回-1。
假如必要,阻塞(或等 待)直到数据可用。
当读操作时发 生错误,则抛出IOException异常。
publicint read(byte[]rgb, intnOff,intnLen)throws IOException
从输入“流”读一指定长度的字节 序列并且置于指定的数组中指定偏移上。
返回所读的字节数。
假如已经到了输入“流”的结尾, 则返回-1。
假如必要,阻塞(或等 待)直到数据可用。
当读操作时发 生错误,则抛出IOException异常。
publiclong skip(longn) throws IOException
跳过指定 的字节数。
返回跳过的字节数。
假如已经到了输入“流”的结尾, 则返回-1。
当操作时发生错误,则 抛出IOException异常。
publicinta vailable() throws IOException
返回可以 从输入“流”中读取的字节数,而不产生读操作阻塞。
当操作时发生错误,则抛 出IOException异常。
publicvoid close()throws IOException
关闭输入“流”,释 放所有与此输入“流”有关的资源(例如操作系统文件句柄)。
当操作时发生错误,则抛 出IOException异常。
publicvoid mark(int nReadLimit)
在输入“流”中标识 当前位置,以后当调用reset()时,输入“流”将重新定位在此位置上。
指定在标识无效之前,标识之后 能读取的字节数。
publicvoid reset()throws IOException
将输入“流”重新定 位在最近标识的位置上。
假如“ 流”没有标识,或者标识已经无效,则抛出IOException异常。
public boolean mark Supported()
显示此输入“ 流”是否支持mark和reset操作。
通用输出“流”类方法
以下是对所有输出“流”通用的方 法,与前一部分一样,每个方法说明之后列出了方法能执行的任务。
publicvoid write(byteb) throws IOException
将一个字 节写入输出“流”。
阻塞(或等待) 直到数据真正写入。
当写操作时 发生错误,则抛出IOException异常。
publicvoid write(byte[] rgb)throws IOException
将一 个字节序列写入输出“流”。
阻塞( 或等待)直到数据真正写入。
当写操作时发生错误,则抛出IOException异常。
publicvoid write (byte[] rgb,intnOff,intnLen) throws IOException
将一个指定长度的字节序列从指 定的偏移量开始写入输出“流”。
阻塞(或等待)直到数据真正写入。
当写操作时发生错误,则抛 出IOException异常。
publicvoid flush ()throws IOException
“冲洗”输出“流”, 立即写所有的缓冲数据。
当操作 时发生错误,则抛出IOException异常。
publicvoidclose()throws IOException
关闭输出“流”,释 放所有与此输出“流”有关的资源(例如操作系统文件句柄)。
当操作时发生错误,则抛 出IOException异常。
攻击计划
本文的代码有三种形式,这是因 为:在Java1.0.2中字节到字符的转换有重要的瑕疵(使语言对Unicode的支持无实质用处),为 了支持国际化,这个瑕疵在Java1.1中得到了修正。结果是产生两套几乎相同的API,仅仅在提 供给字节到字符的转换的方法有所区别。为了给所有人提供可工作的代码,以及显示API是如何 改变的,我们用三个包提供代码,必要时可以下载所有三个包做比较,也可以下载适合你平台的 包。
第一个包运行在Java1.0.2, 有tar文件和zip文件。
第二个包运行在Java1.1,也 有tar文件和zip文件。
第三个包同时运行在Java1.0.2 和Java1.1,这个包没有使用API中冲突的部分,它自己完成工作,你假如对可移植性更感爱好, 可以以tar文件或者zip文件下载此包。本文的代码不是以小程序(Applets)的方式运行,所以你 需要Java Develop ment Kit或者类似的命令行环境。
首先在你的系统中用正确的方 法解开下载的文件,然后在命令行下按照如下命令执行Java Runtime:%javaMain [keyWord] [keyword]...[emailfile]。你可以在命令行中指定任意多的要害字(Keywords)。程 序对每个要害字建立一个“过滤器”,然后将它们一起连接入一个“流”。当输入以标准输入 进入时,程序从标准输入中读取数据,通过“流”传送这些数据,写入标准输出中。假如有一 个“过滤器”检测到一个要害字,就会产生一个异常,以结束程序。这种解决方案很简单,但 是非常有用而且高效。
更多精彩
赞助商链接