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