70. SequenceInputStream(文件合并)
缓冲输入字节流:
----------------------| InputStream 输入字节流的基类
----------------| FileInputStream 读取文件的输入字节流
----------------| BufferedInputStream 缓冲输入字节流 作用:提高读取文件的效率
缓冲输出字节流:
----------------------| OutputStream 输出字节流的基类
----------------| FileOutputStream 写入文件的输入字节流
----------------| BufferedOutputStream 缓冲输出字节流 作用:提高我们写入数据的效率
输入字符流:
--------------| Reader 输入字符流的基类。 抽象类
----------| FileReader 读取文件的输入字符流
----------| BufferedReader 缓存输入字符流(提高效率和扩展了FileReader的功能)。内部其实也维护了一个字符数组
扩展功能:
readLine() 一次读取文本的一行数据,如果读取到了文件末尾返回null
输出字符流:
--------------| Write 输出字符流的基类。 抽象类
----------| FileWrite 向文件输入数据
----------| BufferedWrite 缓存输出字符流。 内部维护了一个字符数组,当我们使用write的时候是把数据存储到了字符数组中,并不是写入了文件中
当我们使用flush,close方法或者数组满了的时候,才会写入文件中
扩展功能:
newLine() 添加一个回车符,实际上就是输出(/r/n)
//需求:把a.txt 和 b.txt的文本合并成一个文本
public class Demo1 {
public static void main(String[] args) throws IOException {
//找到目标文件
File inputfile1 = new File("D:\\新建文件夹\\a.txt");
File inputfile2 = new File("D:\\新建文件夹\\b.txt");
File outputfile = new File("D:\\新建文件夹\\c.txt");
//建立数据通道
FileInputStream fileInputStream1 = new FileInputStream(inputfile1);
FileInputStream fileInputStream2 = new FileInputStream(inputfile2);
FileOutputStream fileOutputStream = new FileOutputStream(outputfile);
//我们建立一个集合来存储被合并文本的数据通道对象
ArrayList<FileInputStream> arrayList = new ArrayList<FileInputStream>();
arrayList.add(fileInputStream1);
arrayList.add(fileInputStream2);
//创建缓存字节数组
byte[] buf = new byte[1024];
//定义变量用来存储每次读取到数组中的字符长度
int length = 0;
for (FileInputStream fileInputStream : arrayList) {
while((length = fileInputStream.read(buf))!= -1) {
//把读取的数据写入c.txt文本中,
fileOutputStream.write(buf,0,length);
}
}
//先开后关原则
fileOutputStream.close();
fileInputStream2.close();
fileInputStream1.close();
}
}
我们可以发现,用上面的方式很不方便,书写很麻烦很繁琐
sun公司给我们提供了一个SequenceInputStream类:
表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,
接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止
其实我们可以发现,它的底层也是存在一个有序集合,原理一样都是遍历有序集合
SequenceInputStream的构造方法:
SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节
SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
SequenceInputStream的常用方法:
close() 关闭此输入流并释放与此流关联的所有系统资源。
read() 从此输入流中读取下一个数据字节。
read(byte[] b, int off, int len) 将最多 len 个数据字节从此输入流读入 byte 数组。
//使用第一个构造方法实现2个文件合并SequenceInputStream(InputStream s1, InputStream s2)
public class Demo2 {
public static void main(String[] args) throws IOException {
//找到目标文件的父路径
File inputfile1 = new File("D:\\新建文件夹\\a.txt");
File inputfile2 = new File("D:\\新建文件夹\\b.txt");
File outputfile = new File("D:\\新建文件夹\\c.txt");
//建立数据通道
FileInputStream fileInputStream1 = new FileInputStream(inputfile1);
FileInputStream fileInputStream2 = new FileInputStream(inputfile2);
FileOutputStream fileOutputStream = new FileOutputStream(outputfile);
SequenceInputStream sequenceInputStream = new SequenceInputStream(fileInputStream1, fileInputStream2);
//创建一个缓存字节数组
byte[] buf = new byte[1024];
int length = 0;
while((length = sequenceInputStream.read(buf))!= -1) {
fileOutputStream.write(buf, 0, length);
}
//先开后关原则
fileOutputStream.close();
sequenceInputStream.close();
}
}
那么如果我们有很多个文件要合并呢?
第二个构造方法:SequenceInputStream(Enumeration<? extends InputStream> e)
此构造方法要接受一个Vector集合的迭代器
有序集合的体系:
-----------------| List 如果实现了List接口的集合类,具备的特点是:有序,可重复
-------------| ArrayList ArrayList底层维护的是一个Object类型的数组,特点是:查询快,增删慢
-------------| LinkList LinkedList底层使用了链表数据结构实现的。特点是:查询慢,增删快
-------------| Vector 底层也是维护了一个Object类型的数组,实现与ArrayList一样,但是Vector线程安全,操作效率低
Vector中的方法:
elements() 返回一个Enumeration<E>类型的迭代器
Enumeration接口中的方法:
hasMoreElements() 判断是否还有下一个元素,有返回true,没有返回false
nextElement() 返回下一个元素
//使用第二个构造方法实现2个文件合并SequenceInputStream(Enumeration<? extends InputStream> e)
public class Demo3 {
public static void main(String[] args) throws IOException {
//找到目标文件的父路径
File inputfile1 = new File("D:\\新建文件夹\\a.txt");
File inputfile2 = new File("D:\\新建文件夹\\b.txt");
File inputfile3 = new File("D:\\新建文件夹\\c.txt");
File outputfile = new File("D:\\新建文件夹\\d.txt");
//建立数据通道
FileInputStream fileInputStream1 = new FileInputStream(inputfile1);
FileInputStream fileInputStream2 = new FileInputStream(inputfile2);
FileInputStream fileInputStream3 = new FileInputStream(inputfile3);
FileOutputStream fileOutputStream = new FileOutputStream(outputfile);
//把数据通道对象放入Vector有序集合中
Vector<FileInputStream> vector = new Vector<FileInputStream>();
vector.add(fileInputStream1);
vector.add(fileInputStream2);
vector.add(fileInputStream3);
//获取迭代器
Enumeration<FileInputStream> e = vector.elements();
//创建SequenceInputStream(Enumeration<? extends InputStream> e)对象
SequenceInputStream sequenceInputStream = new SequenceInputStream(e);
//创建缓存字节数组
byte[] buf = new byte[1024];
//定义变量,用来存储每次存入数组中字节数组的数据长度
int length = 0;
//读取所有需要合并的文本并放入数组中
while((length = sequenceInputStream.read(buf))!= -1) {
//把数组中的文件写入d.txt文本中
fileOutputStream.write(buf, 0, length);
}
fileOutputStream.close();
sequenceInputStream.close();
}
}
练习:
需求1:把一个MP3格式音乐切割成n份
解决:我们可以控制缓存数组的大小,用来分割。如果一个文件的大小是10MB那么我们可以把字节数组大小定义为1MB,那么每次读取的数据是1MB,
然后我们把每次读取的数据都放在不同文件中,那么就实现了切割了
需求2:把切割成n份MP3格式的音乐还原
public class Demo4 {
public static void main(String[] args) throws Exception {
//splitMP3();
mergeMP3();
}
//需求1:把一个MP3格式音乐切割成n份(注意:被分割的音乐可以播放哦)
public static void splitMP3() throws IOException {
//输入的目标
File inputfile = new File("D:\\新建文件夹\\阿杜 - 撕夜.mp3");
//输出的目标文件的父目录
File outputparentfile = new File("D:\\新建文件夹");
//建立数据通道
FileInputStream fileInputStream = new FileInputStream(inputfile);
//建立缓存字节数组,并定义数组大小为1MB(1024字节 = 1kb 1014kb = 1MB)
byte[] buf = new byte[1024*1024];
//定义存储每次读取数据的长度的变量
int length = 0;
//读取文件并进行分割
for(int i = 1 ; (length = fileInputStream.read(buf))!=-1 ; i++) {
FileOutputStream fileOutputStream = new FileOutputStream(new File(outputparentfile, "part"+i+".mp3"));
fileOutputStream.write(buf, 0, length);
fileOutputStream.close();
}
fileInputStream.close();
}
//需求2:把切割成n份MP3格式的音乐还原(不按照顺序合并也可以听哦)
public static void mergeMP3() throws IOException {
//创建输入文件的父路径
File inputparentfile = new File("D:\\新建文件夹");
//创建Vector有序集合
Vector<FileInputStream> vector = new Vector<FileInputStream>();
//定义File类的数组并存储在父路径找到的所有文件的绝对路径
File[] files = inputparentfile.listFiles();
//遍历数组
for (File temp : files) {
//筛选出后缀名为MP3的文件temp:文件的绝对路径 getName()文件的名字 endsWith()文件的后缀名
if(temp.getName().endsWith(".mp3")) {
vector.add(new FileInputStream(temp));
}
}
//获取vector的迭代器
Enumeration<FileInputStream> e = vector.elements();
//创建输出文件的绝对路径
File outputfile = new File("D:\\新建文件夹\\合并.mp3");
//创建输出数据通道
FileOutputStream fileOutputStream = new FileOutputStream(outputfile);
//创建SequenceInputStream对象
SequenceInputStream sequenceInputStream = new SequenceInputStream(e);
//创建缓存数组
byte[] buf = new byte[1024];
//定义存储每次读取到数据的长度的变量
int length = 0;
//边读边写
while((length = sequenceInputStream.read(buf))!= -1) {
fileOutputStream.write(buf, 0, length);
}
}
}
70. SequenceInputStream(文件合并)的更多相关文章
- Java学习笔记——SequenceInputStream类合并文件的综合举例分析
SequenceInputStream 介绍 SequenceInputStream 类表示其他输入流的逻辑串联,即文件的合并. 它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾, ...
- IO综合练习--文件切割和文件合并
有时候一个视频文件或系统文件太大了,上传和下载可能会受到限制,这时可以用文件切割器把文件按大小切分为文件碎片, 等到要使用这个文件了,再把文件碎片合并成原来的文件即可.下面的代码实现了文件切割和文件合 ...
- Day 18:SequenceInputStream、合并切割mp3、对象输入输出流对象
SequenceInputStream用例题讲述用法 需求:1.把a.txt与b.txt 文件的内容合并 2.把a.txt与b.txt .c.txt文件的内容合并 import java.io.Fil ...
- CDN的combo技术能把多个资源文件合并引用,减少请求次数
CDN的combo技术能把多个资源文件合并引用,减少请求次数.比如淘宝的写法: <link rel="stylesheet" href="//g.alicdn.co ...
- linux 两个文件合并
可以使用cat命令,有两种实现的方式,一种将两个文件合并的到一个新的文件,另一种将一个文件追加到另一个文件的末尾. 方法一:使用cat命令从文件中读入两个文件,然后将重定向到一个新的文件.这种方法可以 ...
- grunt配置太复杂?使用Qbuild进行文件合并、压缩、格式化等处理
上次简单介绍了下Qbuild的特点和配置,其实实现一个自动化工具并不复杂,往简单里说,无非就是筛选文件和处理文件.但Qbuild的源码也并不少,还是做了不少工作的. 1. 引入了插件机制.在Qbuil ...
- js或css文件合并的三种方式推荐
源文档 <http://www.jb51.net/article/32834.htm> 在Web项目的开发中,js,css文件会随着项目的开发变得越来越多,越来越大,这就给给性能方面带来一 ...
- AngularJS结合RequireJS做文件合并压缩的那些坑
我在项目使用了AngularJS框架,用RequireJS做异步模块加载(AMD),在做文件合并压缩时,遇到了一些坑,有些只是解决了,但不明白原因. 那些坑 1. build.js里面的paths必须 ...
- 前端js文件合并三种方式
最近在思考前端js文件该如何合并,当然不包括不能合并文件,而是我们能合并的文件,想了想应该也只有三种方式. 三个方式如下: 1. 一个大文件,所有js合并成一个大文件,所有页面都引用它. 2. 各个页 ...
随机推荐
- java命令-jstat/ javap
jstat命令对应用程序资源和性能进行实时监控 常用参数列举如下: 1. jstat -class pid 显示加载class的数量.所占空间.所耗时间等信息 2.jstat -compiler pi ...
- python bezier 曲线
1.手写bezier公式,生成bezier代码, 如果给的点数过多,则会生成一半bezier曲线,剩下的一半就需要进行拼接: import numpy as np import matplotlib. ...
- html 中 获取百度代码
1.登录百度地图api,地址:http://api.map.baidu.com/lbsapi/creatmap/index.html 2.设置你的地理位置,以北京大学为例子如图:
- shell脚本编程运算
一算术运算 bash中的算术运算:help let+, -, *, /, %取模(取余), **(乘方)实现算术运算:(1) let var=算术表达式(2) var=$[算术表达式](3) var= ...
- ansible_playbook语法中的循环语句归纳
种类一.标准循环添加多个用户 - name: add several users user: name={{ item }} state=present groups=wheel with_items ...
- Ruby 技能图谱
# Ruby 技能图谱 说明: 本图谱只捡重点的列举,并非包含全部.文中所列举或没有列举的资源信息都可以在[awesome-ruby](https://github.com/markets/aweso ...
- GIL - global interpreter lock
python是一个解释型语言,但是可以使用多个解释器.比如C++,但是可以用不同的编译器来编译成可执行代码.有名的编译器例如GCC,INTEL C++,Visual C++等.Python也一样,同样 ...
- https://www.cnblogs.com/limanjihe/p/10184327.html
https://www.cnblogs.com/limanjihe/p/10184327.html https://blog.csdn.net/xnnswmzdszyd/article/details ...
- CTF隐写——越光宝盒
0x题目 原题来自于实验吧:http://www.shiyanbar.com/ctf/1992 一句话,和一个PNG图片. 0x解题 1.下载图片以后,发现打不开. 首先想到的就是文件头可能被修改了, ...
- Java学习之面向对象---继承
继承:子继承父,子可以拥有父的所有. 继承的好处: 1.提高了代码的复用性 2.让类与类之间产生了关系.有了这个关系,才有了多态的特性 Java 只支持单继承,不支持多继承 class A { voi ...