友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
Java编程思想第4版[中文版](PDF格式)-第77部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
个简单的例子展示了这些方法的使用:
//: Redirecting。java
// Demonstrates the use of redirection for
// standard IO in Java 1。1
import java。io。*;
class Redirecting {
public static void main(String'' args) {
try {
BufferedInputStream in =
new BufferedInputStream(
new FileInputStream(
〃Redirecting。java〃));
// Produces deprecation message:
PrintStream out =
new PrintStream(
new BufferedOutputStream(
new FileOutputStream(〃test。out〃)));
System。setIn(in);
System。setOut(out);
System。setErr(out);
BufferedReader br =
new BufferedReader(
310
…………………………………………………………Page 312……………………………………………………………
new InputStreamReader(System。in));
String s;
while((s = br。readLine()) != null)
System。out。println(s);
out。close(); // Remember this!
} catch(IOException e) {
e。printStackTrace();
}
}
} ///:~
这个程序的作用是将标准输入同一个文件连接起来,并将标准输出和错误重定向至另一个文件。
这是不可避免会遇到“反对”消息的另一个例子。用…deprecation 标志编译时得到的消息如下:
Note:The constructor java。io。PrintStream(java。io。OutputStream) has been deprecated。
注意:不推荐使用构建器java。io。PrintStream (java。io。OutputStream)。
然而,无论 System。setOut()还是System。setErr()都要求用一个 PrintStream 作为参数使用,所以必须调用
PrintStream 构建器。所以大家可能会觉得奇怪,既然 Java 1。1 通过反对构建器而反对了整个
PrintStream,为什么库的设计人员在添加这个反对的同时,依然为System 添加了新方法,且指明要求用
PrintStream,而不是用 PrintWriter 呢?毕竟,后者是一个崭新和首选的替换措施呀?这真令人费解。
10。8 压缩
Java 1。1 也添加一个类,用以支持对压缩格式的数据流的读写。它们封装到现成的 IO类中,以提供压缩功
能。
此时Java 1。1 的一个问题显得非常突出:它们不是从新的Reader 和Writer 类衍生出来的,而是属于
InputStream和 OutputStream 层次结构的一部分。所以有时不得不混合使用两种类型的数据流(注意可用
InputStreamReader和OutputStreamWriter 在不同的类型间方便地进行转换)。
Java 1。1 压缩类 功能
CheckedInputStream GetCheckSum()为任何 InputStream 产生校验和(不仅是解压)
CheckedOutputStream GetCheckSum()为任何OutputStream 产生校验和(不仅是解压)
DeflaterOutputStream 用于压缩类的基础类
ZipOutputStream 一个DeflaterOutputStream,将数据压缩成Zip 文件格式
GZIPOutputStream 一个DeflaterOutputStream,将数据压缩成GZIP 文件格式
InflaterInputStream 用于解压类的基础类
ZipInputStream 一个 DeflaterInputStream,解压用Zip 文件格式保存的数据
GZIPInputStream 一个DeflaterInputStream,解压用GZIP 文件格式保存的数据
尽管存在许多种压缩算法,但是Zip 和 GZIP 可能最常用的。所以能够很方便地用多种现成的工具来读写这些
格式的压缩数据。
10。8。1 用 GZIP 进行简单压缩
GZIP 接口非常简单,所以如果只有单个数据流需要压缩(而不是一系列不同的数据),那么它就可能是最适
当选择。下面是对单个文件进行压缩的例子:
//: GZIPpress。java
// Uses Java 1。1 GZIP pression to press
// a file whose name is passed on the mand
// line。
311
…………………………………………………………Page 313……………………………………………………………
import java。io。*;
import java。util。zip。*;
public class GZIPpress {
public static void main(String'' args) {
try {
BufferedReader in =
new BufferedReader(
new FileReader(args'0'));
BufferedOutputStream out =
new BufferedOutputStream(
new GZIPOutputStream(
new FileOutputStream(〃test。gz〃)));
System。out。println(〃Writing file〃);
int c;
while((c = in。read()) != …1)
out。write(c);
in。close();
out。close();
System。out。println(〃Reading file〃);
BufferedReader in2 =
new BufferedReader(
new InputStreamReader(
new GZIPInputStream(
new FileInputStream(〃test。gz〃))));
String s;
while((s = in2。readLine()) != null)
System。out。println(s);
} catch(Exception e) {
e。printStackTrace();
}
}
} ///:~
压缩类的用法非常直观——只需将输出流封装到一个GZIPOutputStream 或者ZipOutputStream 内,并将输入
流封装到GZIPInputStream 或者ZipInputStream 内即可。剩余的全部操作就是标准的IO读写。然而,这是
一个很典型的例子,我们不得不混合使用新旧 IO流:数据的输入使用Reader 类,而 GZIPOutputStream 的构
建器只能接收一个 OutputStream 对象,不能接收Writer 对象。
10。8。2 用 Zip 进行多文件保存
提供了 Zip 支持的 Java 1。1 库显得更加全面。利用它可以方便地保存多个文件。甚至有一个独立的类来简化
对Zip 文件的读操作。这个库采采用的是标准Zip 格式,所以能与当前因特网上使用的大量压缩、解压工具
很好地协作。下面这个例子采取了与前例相同的形式,但能根据我们需要控制任意数量的命令行参数。除此
之外,它展示了如何用 Checksum 类来计算和校验文件的“校验和”(Checksum )。可选用两种类型的
Checksum :Adler32 (速度要快一些)和CRC32 (慢一些,但更准确)。
//: Zippress。java
// Uses Java 1。1 Zip pression to press
// any number of files whose names are passed
// on the mand line。
import java。io。*;
import java。util。*;
312
…………………………………………………………Page 314……………………………………………………………
import java。util。zip。*;
public class Zippress {
public static void main(String'' args) {
try {
FileOutputStream f =
new FileOutputStream(〃test。zip〃);
CheckedOutputStream csum =
new CheckedOutputStream(
f; new Adler32());
ZipOutputStream out =
new ZipOutputStream(
new BufferedOutputStream(csum));
out。setment(〃A test of Java Zipping〃);
// Can't read the above ment; though
for(int i = 0; i 《 args。length; i++) {
System。out。println(
〃Writing file 〃 + args'i');
BufferedReader in =
new BufferedReader(
new FileReader(args'i'));
out。putNextEntry(new ZipEntry(args'i'));
int c;
while((c = in。read()) != …1)
out。write(c);
in。close();
}
out。close();
// Checksum valid only after the file
// has been closed!
System。out。println(〃Checksum: 〃 +
csum。getChecksum()。getValue());
// Now extract the files:
System。out。println(〃Reading file〃);
FileInputStream fi =
new FileInputStream(〃test。zip〃);
CheckedInputStream csumi =
new CheckedInputStream(
fi; new Adler32());
ZipInputStream in2 =
new ZipInputStream(
new BufferedInputStream(csumi));
ZipEntry ze;
System。out。println(〃Checksum: 〃 +
csumi。getChecksum()。getValue());
while((ze = in2。getNextEntry()) != null) {
System。out。println(〃Reading file 〃 + ze);
int x;
while((x = in2。read()) != …1)
System。out。write(x);
}
in2。close();
313
…………………………………………………………Page 315……………………………………………………………
// Alternative way to open and read
// zip files:
ZipFile zf = new ZipFile(〃test。zip〃);
Enumeration e = zf。entries();
while(e。hasMoreElements()) {
ZipEntry ze2 = (ZipEntry)e。nextElement();
System。out。println(〃File: 〃 + ze2);
// 。。。 and extract the data as before
}
} catch(Exception e) {
e。printStackTrace();
}
}
} ///:~
对于要加入压缩档的每一个文件,都必须调用 putNextEntry(),并将其传递给一个ZipEntry 对象。
ZipEntry 对象包含了一个功能全面的接口,利用它可以获取和设置 Zip 文件内那个特定的 Entry (入口)上
能够接受的所有数据:名字、压缩后和压缩前的长度、日期、CRC 校验和、额外字段的数据、注释、压缩方
法以及它是否一个目录入口等等。然而,虽然 Zip 格式提供了设置密码的方法,但Java 的Zip 库没有提供这
方面的支持。而且尽管 CheckedInputStream 和CheckedOutputStream 同时提供了对Adler32 和CRC32 校验和
的支持,但是ZipEntry 只支持 CRC 的接口。这虽然属于基层Zip 格式的限制,但却限制了我们使用速度更快
的Adler32。
为解压文件,ZipInputStream 提供了一个 getNextEntry()方法,能在有的前提下返回下一个ZipEntry 。作
为一个更简洁的方法,可以用 ZipFile 对象读取文件。该对象有一个 entries()方法,可以为 ZipEntry 返回
一个Enumeration (枚举)。
为读取校验和,必须多少拥有对关联的Checksum 对象的访问权限。在这里保留了指向CheckedOutputStream
和CheckedInputStream 对象的一个句柄。但是,也可以只占有指向Checksum 对象的一个句柄。
Zip 流中一个令人困惑的方法是 setment()。正如前面展示的那样,我们可在写一个文件时设置注释内
容,但却没有办法取出 ZipInputStream 内的注释。看起来,似乎只能通过ZipEntry 逐个入口地提供对注释
的完全支持。
当然,使用 GZIP 或Zip 库时并不仅仅限于文件——可以压缩任何东西,包括要通过网络连接发送的数据。
10。8。3 Java 归档(jar )实用程序
Zip 格式亦在Java 1。1 的JAR (Java ARchive)文件格式中得到了采用。这种文件格式的作用是将一系列文
件合并到单个压缩文件里,就象Zip 那样。然而,同Java 中其他任何东西一样,JAR 文件是跨平台的,所以
不必关心涉及具体平台的问题。除了可以包括声音和图像文件以外,也可以在其中包括类文件。
涉及因特网应用时,JAR 文件显得特别有用。在 JAR 文件之前,Web 浏览器必须重复多次请求Web 服务器,以
便下载完构成一个“程序片”(Applet)的所有文件。除此以外,每个文件都是未经压缩的。但在将所有这
些文件合并到一个 JAR 文件里以后,只需向远程服务器发出一次请求即可。同时,由于采用了压缩技术,所
以可在更短的时间里获得全部数据。另外,JAR 文件里的每个入口(条目)都可以加上数字化签名(详情参
考Java 用户文档)。
一个JAR 文件由一系列采用 Zip 压缩格式的文件构成,同时还有一张“详情单”,对所有这些文件进行了描
述(可创建自己的详情单文件;否则,jar程序会为我们代劳)。在联机用户文档中,可以找到与JAR 详情
单更多的资料(详情单的英语是“Manifest ”)。
jar 实用程序已与Sun 的JDK 配套提供,可以按我们的选择自动压缩文件。请在命令行调用它:
jar '选项' 说明 '详情单' 输入文件
其中,“选项”用一系列字母表示(不必输入连字号或其他任何指示符)。如下所示:
c 创建新的或空的压缩档
t 列出目录表
314
…………………………………………………………Page 316……………………………………………………………
x 解压所有文件
x file 解压指定文件
f 指出“我准备向你提供文件名”。若省略此参数,jar 会假定它的输入来自标准输入;或者在它创建文件
时,输出会进入标准输出内
m 指出第一个参数将是用户
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!