Java开发笔记(九十一)IO流处理简单的数据压缩
前面介绍的文件I/O,不管是写入文本还是写入对象,文件中的数据基本是原来的模样,用记事本之类的文本编辑软件都能浏览个大概。这么存储数据,要说方便确实方便,只是不够经济划算,原因有二:其一,写入的数据可能存在大量重复的信息,但依原样写到文件的话,无疑保留了不少冗余数据,造成空间浪费;其二,写入的数据多以明文方式保存,容易产生信息泄露,安全性不高。为此Java提供了简单的压缩和解压工具,在将数据写入文件之前,先对数据进行压缩,再将压缩后的结果写到文件;同样读取压缩文件之时,先读出已压缩的数据,再将这些数据进行解压,解压后的结果即为最初的原始数据。
在IO流的家族体系中,压缩与解压操作需要GZIPOutputStream、GZIPInputStream、ByteArrayOutputStream、ByteArrayInputStream这四个工具类互相配合,分别简述如下:
GZIPOutputStream:压缩输出流。它吃进去的是原始数据的字节数组,拉出来的是字节数组输出流对象(压缩后的数据)。
ByteArrayOutputStream:字节数组输出流。它从压缩输出流获取压缩后的数据,并通过toByteArray方法输出字节数组信息。或者从压缩输入流获取解压后的数据,并通过toByteArray方法输出字节数组信息。
GZIPInputStream:压缩输入流。它吃进去的是字节数组输入流对象(压缩后的数据),拉出来的是解压后的字节数组(原始数据)。
ByteArrayInputStream:字节数组输入流。它输入压缩数据的字节数组,转成流对象后丢给压缩输入流。
上面的工具介绍描述看上去索然无味,确实要运用到实际案例中才比较好理解。接下来先来瞧瞧原始字符串是怎么变成压缩数据的,详细的压缩过程代码示例如下:
// 从字符串获得压缩后的字节数组
private static byte[] compress(String str) {
if (str==null || str.length()<=0) {
return null;
}
byte[] zip_bytes = null; // 声明压缩数据的字节数组
// 先构建字节数组输出流,再据此构建压缩输出流
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gos = new GZIPOutputStream(baos);) {
gos.write(str.getBytes()); // 往压缩输出流写入字节数组
gos.finish(); // 结束写入操作
zip_bytes = baos.toByteArray(); // 从字节数组输出流中获取字节数组信息
} catch (Exception e) {
e.printStackTrace();
}
return zip_bytes;
}
既已得到压缩后的字节数组,将其写入文件之中真是易如反掌,下面是往文件写入压缩数据的代码例子:
// 往文件写入压缩后的数据
private static void writeZipFile() {
String str = "白日依山尽,黄河入海流。\n欲穷千里目,更上一层楼。";
// 根据指定文件路径构建文件输出流对象
try (FileOutputStream fos = new FileOutputStream(mFileName)) {
// 从字符串获得压缩后的字节数组
byte[] zip_bytes = compress(str);
fos.write(zip_bytes); // 把字节数组写入文件输出流
} catch (Exception e) {
e.printStackTrace();
}
}
再来看看如何从压缩文件中读到解压后的原始数据,把压缩后的数据还原为初始字符串要复杂一些,需要ByteArrayInputStream、GZIPInputStream、ByteArrayOutputStream三个工具互相配合,具体的解压过程代码如下所示:
// 从压缩字节数组获得解压后的字符串
private static String uncompress(byte[] bytes) {
if (bytes==null || bytes.length<=0) {
return null;
}
byte[] unzip_bytes = null; // 声明解压数据的字节数组
// 分别构建字节数组输出流,以及字节数组输入流,并根据字节数组输入流构建压缩输入流
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
GZIPInputStream gis = new GZIPInputStream(bais);) {
byte[] buffer = new byte[1024];
while (true) {
// 从压缩输入流中读取数据到字节数组,并返回读到的数据长度
int length = gis.read(buffer);
if (length < 0) { // 未读到数据,表示已经读完了
break;
}
baos.write(buffer); // 往字节数组输出流写入字节数组
}
unzip_bytes = baos.toByteArray(); // 从字节数组输出流中获取字节数组信息
} catch (Exception e) {
e.printStackTrace();
}
return new String(unzip_bytes); // 把字节数组转换为字符串,并返回该字符串
}
利用刚刚编写的uncompress解压方法,很容易从压缩文件中得到原始字符串,下面是从压缩文件读取解压数据的代码例子:
// 从压缩文件中读取解压后的数据
private static void readZipFile() {
// 根据指定文件路径构建文件输入流对象
try (FileInputStream fis = new FileInputStream(mFileName)) {
// 分配长度为文件大小的字节数组。available方法返回当前未读取的大小
byte[] bytes = new byte[fis.available()];
fis.read(bytes); // 从文件输入流中读取字节数组
// 从压缩字节数组获得解压后的字符串
String content = uncompress(bytes);
System.out.println("content="+content);
} catch (Exception e) {
e.printStackTrace();
}
}
更多Java技术文章参见《Java开发笔记(序)章节目录》
Java开发笔记(九十一)IO流处理简单的数据压缩的更多相关文章
- Java开发笔记(五十八)简单接口及其实现
前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...
- Java精选笔记_其他IO流(ObjectInputStream、DataInputStream、PrintStream、标准输入输出流)
其他IO流 ObjectInputStream和ObjectOutputStream 如果希望永久将对象转为字节数据写入到硬盘上,即对象序列化,可以使用ObjectOutputStream(对象输出流 ...
- Java开发笔记(序)章节目录
现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...
- Java开发笔记(九十)对象序列化及其读写
有些时候,开发者想把程序运行过程中的数据临时保存到文件,可是前面介绍的字符流和字节流,要么用来读写文本字符串,要么用来读写字节数组,并不能直接保存某个对象信息,因为对象里面包括成员属性和成员方法,单就 ...
- Java开发笔记(九十二)文件通道的基本用法
前面介绍的各色流式IO在功能方面着实强大,处理文件的时候该具备的操作应有尽有,可流式IO在性能方面不尽如人意,它的设计原理使得实际运行效率偏低,为此从Java4开始增加了NIO技术,通过全新的架构体系 ...
- Java开发笔记(八十八)文件字节I/O流
前面介绍了如何使用字符流读写文件,并指出字符流工具的处理局限,进而给出随机文件工具加以改进.随机文件工具除了支持访问文件内部的任意位置,更关键的一点是通过字节数组读写文件数据,采取字节方式比起字符方式 ...
- Java开发笔记(八十五)通过字符流读写文件
前面介绍了文件的信息获取.管理操作,以及目录下的文件遍历,那么文件内部数据又是怎样读写的呢?这正是本文所要阐述的内容.File工具固然强大,但它并不能直接读写文件,而要借助于其它工具方能开展读写操作. ...
- Java开发笔记(七十二)Java8新增的流式处理
通过前面几篇文章的学习,大家应能掌握几种容器类型的常见用法,对于简单的增删改和遍历操作,各容器实例都提供了相应的处理方法,对于实际开发中频繁使用的清单List,还能利用Arrays工具的asList方 ...
- Java开发笔记(九十五)NIO配套的文件工具Files
NIO不但引进了高效的文件通道,而且新增了更加好用的文件工具家族,包括路径组工具Paths.路径工具Path.文件组工具Files.先看路径组工具Paths,该工具提供了静态方法get,输入某个文件的 ...
随机推荐
- Python单元测试unittest - 单元测试框架
一.unittest简介 unitest单元测试框架最初是有JUnit的启发,它支持测试自动化,共享测试的设置和关闭代码,将测试聚合到集合中,以及测试与报告框架的独立性. 二.unittest相关概念 ...
- zabbix3.0.4关于java服务端程序内存溢出的处理
关于java服务端程序内存溢出的处理 java服务端程序内存溢出会产生jvm.log文件,此时程序会挂掉,无法正常处理业务,需要重启服务 思路: 当存在jvm.log这个文件的时候则触发clean_j ...
- 在Mac上安装GTK(go语言GUI)
1.在终端输入:xcode-select --install 安装command line工具, 如果安装了Xcode, 就直接跳过该步骤 2. 在终端输入:ruby -e "$(curl ...
- 转:vue+element实现树形组件
项目中需要用到树形组件,在网上发现一个用vue+element实现的树形组件,现在记录下: demo地址:https://github.com/wilsonIs/vue-treeSelect
- CSS Grid 布局
CSS Grid 布局是 CSS 中最强大的布局系统.与 flexbox 的一维布局系统不同,CSS Grid 布局是一个二维布局系统,也就意味着它可以同时处理列和行.通过将 CSS 规则应用于 父元 ...
- 使用Java类库POI生成简易的Excel报表
使用Java类库POI生成简易的Excel报表 1.需求 1.数据库生成报表需要转义其中字段的信息.比如 1,有效 2.无效等 2.日期格式的自数据需要转义其格式. 3.标题的格式和数据的格式需要分别 ...
- PHP实现简单倒计时
PHP实现倒计时代码示例如下: <?php $time1 = time(); $time2 = strtotime("2018-10-1"); $time3 = strtot ...
- Codeforces 448C Painting Fence(分治法)
题目链接:http://codeforces.com/contest/448/problem/C 题目大意:n个1* a [ i ] 的木板,把他们立起来,变成每个木板宽为1长为 a [ i ] 的栅 ...
- Ext.Js核心函数( 三)
ExtJs 核心函数简介 1.ExtJs提供的常用函数2.get.fly.getCmp.getDom.getBody.getDoc3.query函数和select函数4.encode函数和decode ...
- Emmet Cheat Sheet(Sublime编辑)
快捷创建html标签 官网的Emmet Cheat Sheet :http://docs.emmet.io/cheat-sheet/ https://files.cnblogs.com/files/t ...