利用JAVAAPI函数实现大数据地压缩与解压缩.doc

上传人:李司机 文档编号:1174056 上传时间:2022-07-13 格式:DOC 页数:19 大小:143KB
返回 下载 相关 举报
利用JAVAAPI函数实现大数据地压缩与解压缩.doc_第1页
第1页 / 共19页
利用JAVAAPI函数实现大数据地压缩与解压缩.doc_第2页
第2页 / 共19页
利用JAVAAPI函数实现大数据地压缩与解压缩.doc_第3页
第3页 / 共19页
利用JAVAAPI函数实现大数据地压缩与解压缩.doc_第4页
第4页 / 共19页
利用JAVAAPI函数实现大数据地压缩与解压缩.doc_第5页
第5页 / 共19页
点击查看更多>>
资源描述

《利用JAVAAPI函数实现大数据地压缩与解压缩.doc》由会员分享,可在线阅读,更多相关《利用JAVAAPI函数实现大数据地压缩与解压缩.doc(19页珍藏版)》请在三一办公上搜索。

1、利用JAVA API函数实现数据的压缩与解压缩综述许多信息资料都或多或少的包含一些多余的数据。通常会导致在客户端与服务器之间,应用程序与计算机之间极大的数据传输量。最常见的解决数据存储和信息传送的方法是安装额外的存储设备和扩展现有的通讯能力。这样做是可以的,但无疑会增加组织的运作本钱。一种有效的解决数据存储与信息传输的方法是通过更有效率的代码来存储数据。这篇文章简要的介绍了数据的压缩与解压缩,并展示了用java.util.zip包来实现数据的压缩与解压缩是多么的方便与高效。当然用诸如WinZip,gzip,和Java压缩或jar之类的工具也可以实现数据的压缩与解压缩,这些工具都是独立的应用程序

2、。你也可以在JAVA应用程序中调用这些工具,但这并不是最直接的方法,也不是有效的解决方法。尤其是你想更快速地实现数据的压缩与解压缩例如在传输数据到远程机器之前。这篇文章包括以下容: 给出一个关于数据压缩的简单的介绍 描述java.util.zip包 示例如何使用该包实现数据的压缩与解压缩 示例如何压缩串行化的对象并将其存储在磁碟上 示例如何通过数据压缩来增强客户/服务应用程序的性能 数据压缩概述文件中数据冗余的最简单的类型是字符的复制。让我们先来看下面一个字符串: JJJJJJAAAAVVVVAAAAAA 这个字符串可以用更简洁的方式来编码,那就是通过替换每一个重复的字符串为单个的实例字符加上

3、记录重复次数的数字来表示,上面的字符串可以被编码为下面的形式: 6J4A4V6A 在这里,6J意味着6个字符J,4A意味着4个字符A,以此类推。这种字符串压缩方式称为行程长度编码方式,简称RLE。再举一个例子,考虑一下矩形图像的存储。一个单色位图,可以被存储为下面这种形式,如图1所示。图1:RLE方式下的位图信息另外一种方式是将图像存为一个图元文件:Rectangle 11, 3, 20, 5上面的表示方法是讲矩形的起始坐标是11,3,宽度是20,高度是5。上述的矩形图像可以使用RLE编码方式压缩,通过对一样位记数表示如下:0, 400, 400,10 1,20 0,100,10 1,1 0,

4、18 1,1 0,100,10 1,1 0,18 1,1 0,100,10 1,1 0,18 1,1 0,100,10 1,20 0,100,40上面第一行是讲图像的第一行由40个0组成。第三行是讲图像的第三行是由10个0加上20个1再加上10个0组成,其它行以此类推。大家注意,RLE方法需要将其表示的文件与编码文件分开。所以,这种方法不能应用于所有的文件。其它的压缩技术包括变长编码也被称为哈夫曼编码,还有其它的方法。要想了解更详细的信息,请参考有关数据和图像压缩技术方面的图书,一定会有收获的。数据压缩有很多益处。不管怎么说,最主要的好处就是减少存储方面的需求。同样的,对于数据通信来讲,压缩数

5、据在媒体中的将导致信息传输数据的提升。数据的压缩能够通过软件在现有的硬件设备上实现或者通过带有压缩技术的特殊的硬件设备来实现。图表2显示了根本的数据压缩结构图。图2:数据压缩结构图ZIP VS GZIP如果你是在Windows系统下工作,你可能会对工具WinZip很熟悉,是用来创建压缩档案和解开压缩档案的。而在UNIX平台上,会有一些不同,命令tar用来创建一个档案文件并不压缩,其它的程序gzip或press用来创建一个压缩档案。WinZip和PkZip之类的工具同时扮演着归档和压缩两个角色。他们将文件压缩并将其归档。另一方面,gzip并不将文件归档。所以,在UNIX平台上,命令tar通常用来

6、创建一个档案文件,然后命令gzip来将档案文件压缩。Java提供了java.util.zip包用来兼容ZIP格式的数据压缩。它提供了一系列的类用来读取,创建,修改ZIP和GZIP格式的文件。它还提供了工具类来计算任意输入流的数目,这可以用来验证输入数据的有效性。该包提供了一个接口,十四个类,和两个异常处理类,如表1所示。条目类型描述Checksum接口被类Adler32和CRC32实现的接口Adler32类使用Alder32算法来计算Checksum数目CheckedInputStream类一个输入流,保存着被读取数据的ChecksumCheckedOutputStream类一个输出流,保存着

7、被读取数据的ChecksumCRC32类使用CRC32算法来计算Checksum数目Deflater类使用ZLIB压缩类,支持通常的压缩方式DeflaterOutputStream类一个输出过滤流,用来压缩Deflater格式数据GZIPInputStream类一个输入过滤流,读取GZIP格式压缩数据GZIPOutputStream类一个输出过滤流,读取GZIP格式压缩数据Inflater类使用ZLIB压缩类,支持通常的解压方式InlfaterInputStream类一个输入过滤流,用来解压Inlfater格式的压缩数据ZipEntry类存储ZIP条目ZipFile类从ZIP文件中读取ZIP条

8、目ZipInputStream类一个输入过滤流,用来读取ZIP格式文件中的文件ZipOutputStream类一个输出过滤流,用来向ZIP格式文件口写入文件DataFormatException异常类抛出一个数据格式错误ZipException异常类抛出一个ZIP文件注意:ZLIB压缩类最初是作为可移植的网络图像文件格式PNG标准的一局部开发的,是不受专利保护的。从ZIP文件中解压缩和提取数据java.util.zip包提供了数据压缩与解压缩所需要的类。ZIP文件的解压缩实质上就是从输入流中读取数据。Java.util.zip包提供了类ZipInputStream来读取ZIP文件。ZipInp

9、utStream流的创建与其它输入流的创建没什么两样。举个例子,下面的代码段创建了一个输入流来读取ZIP格式的文件:FileInputStream fis = new FileInputStream(figs.zip);ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis);ZIP输入流打开后,你可以使用getNextEntry方法来读取ZIP文件中的条目数,该方法返回一个ZipEntry对象。如果到达文件的尾部,getNextEntry返回null:ZipEntry entry;while(entry = zi

10、n.getNextEntry() != null) / extract data / open output streams现在,你应该建立一个输出流,如下所示:int BUFFER = 2048;FileOutputStream fos = new FileOutputStream(entry.getName();BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);注意:在这段代码中我们用BufferedOutputStream代替了ZIPOutputStream。ZIPOutputStream和GZIPOutp

11、utStream使用置的512字节缓冲。当缓冲区的大小大于512字节时,使用BufferedOutputStream才是正确的例子中设置为2048。ZIPOutputStream不允许你设置缓冲区的大小,GZIPOutputStream也是一样,但创建 GZIPOutputStream 对象时可以通过构造函数的参数指定置的缓冲尺寸。这段代码中,使用ZIP含的条目名称创建一个文件输出流。可以使用entry.getName来得到它的返回句柄。接着读出被压缩的源数据,然后写入输出流:while (count = zin.read(data, 0, BUFFER) != -1) /System.out

12、.write(x); dest.write(data, 0, count);最后,不要忘记关闭输入和输出流:dest.flush();dest.close();zin.close();例程1的源程序UnZip.java显示如何解压缩并从ZIP档案中将文件释放出来。测试这个例子,编译这个类,并运行它,传给它一个ZIP格式的文件作为参数:注意:somefile.zip应该是一个ZIP压缩档案,可以用任何一种ZIP压缩工具来创建,例如WinZip。例程1源代码:import java.io.*;import java.util.zip.*;public class UnZip static fina

13、l int BUFFER = 2048; public static void main (String argv) try BufferedOutputStream dest = null; FileInputStream fis = new FileInputStream(argv0); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis); ZipEntry entry; while(entry = zis.getNextEntry() != null) System.out.println(Extrac

14、ting: +entry); int count; byte data = new byteBUFFER; / write the files to the disk FileOutputStream fos = new FileOutputStream(entry.getName(); dest = new BufferedOutputStream(fos, BUFFER); while (count = zis.read(data, 0, BUFFER) != -1) dest.write(data, 0, count); dest.flush(); dest.close(); zis.c

15、lose(); catch(Exception e) e.printStackTrace(); 有一点值得大家注意,类ZipInputStream读出ZIP文件序列简单地说就是读出这个ZIP文件压缩了多少文件,而类ZipFile使用嵌的随机文件访问机制读出其中的文件容,所以不必顺序的读出ZIP压缩文件序列。注意:ZIPInputStream和ZipFile之间另外一个根本的不同点在于高速缓冲的使用方面。当文件使用ZipInputStream和FileInputStream流读出的时候,ZIP条目不使用高速缓冲。然而,如果使用ZipFile文件名来打开文件,它将使用嵌的高速缓冲,所以如果ZipF

16、ile文件名被重复调用的话,文件只被打开一次。缓冲值在第二次打开进使用。如果你工作在UNIX系统下,这是什么作用都没有的,因为使用ZipFile打开的所有ZIP文件都在存中存在映射,所以使用ZipFile的性能优于ZipInputStream。然而,如果同一ZIP文件的容在程序执行期间经常改变,或是重载的话,使用ZipInputStream就成为你的首选了。下面显示了使用类ZipFile来解压一个ZIP文件的过程:1. 通过指定一个被读取的ZIP文件,或者是文件名,或者是一个文件对象来创建一个ZipFile对象:2. ZipFile zipfile = new ZipFile(figs.zip

17、);3. 使用entries方法,返回一个枚举对象,循环获得文件的ZIP条目对象:4. while(e.hasMoreElements() 5. entry = (ZipEntry) e.nextElement();6. / read contents and save them7. 8. ZIP条目作为参数传递给getInputStream方法,可以读取ZIP文件中指定条目的容,能过其返回的输入流InputStram对象可以方便的读出ZIP条目的容:9. is = new BufferedInputStream(zipfile.getInputStream(entry);10. 获取ZIP条

18、目的文件名,创建输出流,并保存:11. byte data = new byteBUFFER;12. FileOutputStream fos = new FileOutputStream(entry.getName();13. dest = new BufferedOutputStream(fos, BUFFER);14. while (count = is.read(data, 0, BUFFER) != -1) 15. dest.write(data, 0, count);16. 17. 最后关闭所有的输入输出流 dest.flush();18. dest.close();19. is.

19、close();完整的程序代码如例程2所示。再次编译这个文件,并传递一个ZIP格式的文件做为参数:例程2源码:UnZip2.java import java.io.*;import java.util.*;import java.util.zip.*;public class UnZip2 static final int BUFFER = 2048; public static void main (String argv) try BufferedOutputStream dest = null; BufferedInputStream is = null; ZipEntry entry;

20、 ZipFile zipfile = new ZipFile(argv0); Enumeration e = zipfile.entries(); while(e.hasMoreElements() entry = (ZipEntry) e.nextElement(); System.out.println(Extracting: +entry); is = new BufferedInputStream (zipfile.getInputStream(entry); int count; byte data = new byteBUFFER; FileOutputStream fos = n

21、ew FileOutputStream(entry.getName(); dest = new BufferedOutputStream(fos, BUFFER); while (count = is.read(data, 0, BUFFER) != -1) dest.write(data, 0, count); dest.flush(); dest.close(); is.close(); catch(Exception e) e.printStackTrace(); 将数据压缩归档入一ZIP文件类ZipOutputStream能够用来将数据压缩成一个ZIP文件。ZipOutputStrea

22、m将数据写入ZIP格式的输出流。下面的步骤与创建一个ZIP文件相关。1、第一步是创建一个ZipOutputStream对象,我们将要写入输出流的文件作为参数传给它。下面的代码演示了如何创建一个名为myfigs.zip的ZIP文件。FileOutputStream dest = newFileOutputStream(myfigs.zip);ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest);2、一但目标输出流创建后,下一步就是打开数据源文件。在这个例子中,源数据文件是指那些当前目录下的文件。命令lis

23、t用来得到当前目录下文件列表:File f = new File(.);String files = f.list();for (int i=0; i files.length; i+) System.out.println(Adding: +filesi); FileInputStream fi = new FileInputStream(filesi); / create zip entry / add entries to ZIP file注意:这个例程能够压缩当前目录下的所有文件。它不能处理子目录。作为一个练习,你可以修改例程3来处理子目录。3、 为读出的数据创建一个ZIP条目列表:Z

24、ipEntry entry = new ZipEntry(filesi)4、 在你将数据写入ZIP输出流之前,你必须使用putNextEntry方法将ZIP条目列表写入输出流:out.putNextEntry(entry);5、 将数据写入ZIP文件:int count;while(count = origin.read(data, 0, BUFFER) != -1) out.write(data, 0, count);6、 最后关闭所有的输入输出流:origin.close();out.close();完整的程序代码如例程3所示。例程3源代码:Zip.java import java.io.

25、*;import java.util.zip.*;public class Zip static final int BUFFER = 2048; public static void main (String argv) try BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream(c:zipmyfigs.zip); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest); /out.setMeth

26、od(ZipOutputStream.DEFLATED); byte data = new byteBUFFER; / get a list of files from current directory File f = new File(.); String files = f.list(); for (int i=0; i files.length; i+) System.out.println(Adding: +filesi); FileInputStream fi = new FileInputStream(filesi); origin = new BufferedInputStr

27、eam(fi, BUFFER); ZipEntry entry = new ZipEntry(filesi); out.putNextEntry(entry); int count; while(count = origin.read(data, 0, BUFFER) != -1) out.write(data, 0, count); origin.close(); out.close(); catch(Exception e) e.printStackTrace(); 注意: 条目列表可以以两种方式参加ZIP文件中,一种是压缩方式DEFLATED,另一种是不压缩方式(STORED),系统默认

28、的存储方式为压缩方式DEFLATED。SetMethod方法可以用来设置它的存储方式。例如,设置存储方式为DEFLATED压缩应该这样做: out.setMethod(ZipOutputStream.DEFLATED) 设置存储方式为不压缩应该这样做: out.setMethod(ZipOutputStream.STORED)。ZIP文件属性类ZipEntry描述了存储在ZIP文件中的压缩文件。类中包含有多种方法可以用来设置和获得ZIP条目的信息。类ZipEntry是被ZipFile和ZipInputStream使用来读取ZIP文件,ZipOutputStream来写入ZIP文件的。ZipEn

29、try中最有用的一些方法显示在下面的表格2中,并且有相应的描述。表格 2: 类ZipEntry中一些有用的方法方法签名描述public String getment()返回条目的注释, 没有返回nullpublic long getpressedSize()返回条目压缩后的大小, 未知返回-1public int getMethod()返回条目的压缩方式,没有指定返回 -1public String getName()返回条目的名称public long getSize()返回未被压缩的条目的大小,未知返回-1public long getTime()返回条目的修改时间, 没有指定返回-1pu

30、blic void setment(String c)设置条目的注释public void setMethod(int method)设置条目的压缩方式public void setSize(long size)设置没有压缩的条目的大小public void setTime(long time)设置条目的修改时间求和校验java.util.zip包中另外一些比拟重要的类是Adler32和CRC32,它们实现了java.util.zip.Checksum接口,并估算了压缩数据的校验和checksum。众所周知,在运算速度方面,Adler32算法比CRC32算法要有一定的优势;但在数据可信度方面,

31、CRC32算法如此要更胜一筹。正所谓,鱼与熊掌,不可兼得。,大家只好在不同的场合下,加以取舍了。GetValue方法可以用来获得当前的checksum值,reset方法能够重新设置checksum为其缺省的值。求和校验一般用来校验文件和信息是否正确的传送。举个例子,假设你想创建一个ZIP文件,然后将其传送到远程计算机上。当到达远程计算机后,你就可以使用checksum检验在传输过程中文件是否发生错误。为了演示如何创建checksums,我们修改了例程1和例程3,在例程4和例程5中使用了两个新类,一个是CheckedInputStream,另一个是CheckedOutputStream。大家注意

32、:这两段代码在压缩与解压缩过程中,使用了同一种算法,求数据的checksum值。例程4源代码:Zip.java import java.io.*;import java.util.zip.*;public class Zip static final int BUFFER = 2048; public static void main (String argv) try BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream(c:zipmyfigs.zip); CheckedOutputSt

33、ream checksum = new CheckedOutputStream(dest, new Adler32(); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checksum); /out.setMethod(ZipOutputStream.DEFLATED); byte data = new byteBUFFER; / get a list of files from current directory File f = new File(.); String files = f.list();

34、 for (int i=0; i files.length; i+) System.out.println(Adding: +filesi); FileInputStream fi = new FileInputStream(filesi); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(filesi); out.putNextEntry(entry); int count; while(count = origin.read(data, 0, BUFFER) != -1) out.wri

35、te(data, 0, count); origin.close(); out.close(); System.out.println(checksum: +checksum.getChecksum().getValue(); catch(Exception e) e.printStackTrace(); 例程5源代码:UnZip.java import java.io.*;import java.util.zip.*;public class UnZip public static void main (String argv) try final int BUFFER = 2048; Bu

36、fferedOutputStream dest = null; FileInputStream fis = new FileInputStream(argv0); CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32(); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum); ZipEntry entry; while(entry = zis.getNextEntry() != null) System.out.p

37、rintln(Extracting: +entry); int count; byte data = new byteBUFFER; / write the files to the disk FileOutputStream fos = new FileOutputStream(entry.getName(); dest = new BufferedOutputStream(fos, BUFFER); while (count = zis.read(data, 0, BUFFER) != -1) dest.write(data, 0, count); dest.flush(); dest.c

38、lose(); zis.close(); System.out.println(Checksum: +checksum.getChecksum().getValue(); catch(Exception e) e.printStackTrace(); 测试例程4和5,编译类文件并运行类Zip来创建一个压缩档案程序会计算出checksum值并显示在屏幕上,然后运行UnZip类来解压缩这个档案屏幕上同样会打印出一个checksum值。两个值必须完全一样,否如此说明出错了。Checksums在数据校验方面非常有用。例如,你可以创建一个ZIP文件,然后连同checksum值一同传递给你的朋友。你的朋友

39、解压缩文件后,将生成的checksum值与你提供的作一比拟,如果一样如此说明在传递过程中没有发生错误。压缩对象我们已经看到如何将文件中的数据压缩并将其归档。但如果你想压缩的数据不在文件中时,应该怎么办呢?假设有这样一个例子,你通过套接字socket来传递一个大对象。为了提高应用程序的性能,你可能在通过网络开始传递前将数据压缩,然后在目的地将其解压缩。另外一个例子,我们假设你想将一个对象用压缩格式存储在磁碟上,ZIP格式是基于记录方式的,不适合这项工作。GZIP更适合用来实现这种对单一数据流的操作。现在,我们来示例一下,如果在写入磁碟前将数据压缩,并在读出时将数据解压缩。示例程序6是一个在单一J

40、VMjava虚拟机实现了Serializable接口的简单类,我们想要串行化该类的实例。例程6源代码:Employee.java import java.io.*;public class Employee implements Serializable String name; int age; int salary; public Employee(String name, int age, int salary) this.name = name; this.age = age; this.salary = salary; public void print() System.out.println(Record for: +name); System.out.println(Name: +name); System.out.println(Age: +age); System.out.println(Salary: +salary

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号