1.数据输入输出流的概述和使用
1.数据输入输出流的概述
通过API查看
数据输入和输出流:
数据输入流: DataInputStream
数据输出流: DataOutputStream
特点: 可以写基本数据类型,可以读取基本数据类型
2.案例演示: 数据输入输出流的使用
public class MyTest {
public static void main(String[] args) throws IOException {
// A:
// 数据输入输出流的概述
// 通过API查看
// 数据输入和输出流:
// 数据输入流:
// DataInputStream
// 数据输出流:
// DataOutputStream
// 特点:
// 可以写基本数据类型, 可以读取基本数据类型
//writeData();
//你怎么写的,你就怎么读,顺序不要乱
DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
int i = in.readInt();
double v = in.readDouble();
boolean b = in.readBoolean();
char c = in.readChar();
System.out.println(i);
System.out.println(v);
System.out.println(b);
System.out.println(c);
in.close();
}
private static void writeData() throws IOException {
DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
out.writeInt(100);
out.writeDouble(3.14);
out.writeBoolean(true);
out.writeChar('a');
out.close();
}
}
2.内存操作流的概述和使用
1.内存操作流的概述
a:操作字节数组
ByteArrayOutputStream
ByteArrayInputStream
此流关闭无效,所以无需关闭
b:操作字符数组
CharArrayWrite
CharArrayReader
c:操作字符串
StringWriter
StringReader
2.案例演示: 内存操作流的使用
构造方法: public ByteArrayOutputStream()
内存操作输出流:
public class MyTest {
public static void main(String[] args) throws IOException {
//内存操作流:内存操作流,不关联文件,只在内存中进行读写
/* a:
操作字节数组
ByteArrayOutputStream
ByteArrayInputStream
此流关闭无效,所以无需关闭*/
/*
* ByteArrayOutputStream
* 此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。
* 可使用 toByteArray() 和 toString() 获取数据。
关闭 ByteArrayOutputStream 无效。
此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
* */
// ByteArrayOutputStream()
// 创建一个新的 byte 数组输出流。
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write("好好学习".getBytes());
bos.write("天天向上".getBytes());
bos.write("爱生活,爱Java".getBytes());
//取出所有的字节数据
byte[] bytes = bos.toByteArray();
String s = new String(bytes);
System.out.println(s);
//如果你放的是,String的字节数据,你可以这样取
String s1 = bos.toString();
System.out.println(s1);
}
}
内存操作输入流:
public class MyTest2 {
public static void main(String[] args) {
// ByteArrayInputStream( byte[] buf)
// 创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。
byte[] bytes = "西部开源教育科技有限公司".getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
int data=0;
while ((data=in.read())!=-1){
System.out.println(data);
}
}
}
合并多个文件:
public class MyTest {
public static void main(String[] args) throws IOException {
FileInputStream in1 = new FileInputStream("叶丽仪 - 新上海滩.mp3");
FileInputStream in2 = new FileInputStream("烟花易冷Live_林志炫.mp3");
FileInputStream in3 = new FileInputStream("许巍 - 曾经的你.mp3");
FileInputStream in4 = new FileInputStream("许巍 - 蓝莲花.mp3");
ArrayList<FileInputStream> list = new ArrayList<>();
list.add(in1);
list.add(in2);
list.add(in3);
list.add(in4);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len=0;
byte[] bytes=new byte[1024*8];
for (FileInputStream in : list) {
while ((len=in.read(bytes))!=-1){
bos.write(bytes,0,len);
}
in.close();
}
//把四首歌总字节取出来
byte[] allBytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(allBytes);
FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\歌曲大连唱.mp3");
int len2 = 0;
byte[] bytes2 = new byte[1024 * 8];
while ((len2 = bis.read(bytes2)) != -1) {
out.write(bytes2, 0, len2);
}
out.close();
}
}
public class MyTest2 {
public static void main(String[] args) throws IOException {
FileInputStream in1 = new FileInputStream("叶丽仪 - 新上海滩.mp3");
FileInputStream in2 = new FileInputStream("烟花易冷Live_林志炫.mp3");
FileInputStream in3 = new FileInputStream("许巍 - 曾经的你.mp3");
FileInputStream in4 = new FileInputStream("许巍 - 蓝莲花.mp3");
ArrayList<FileInputStream> list = new ArrayList<>();
list.add(in1);
list.add(in2);
list.add(in3);
list.add(in4);
FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\歌曲大连唱2.mp3");
int len=0;
byte[] bytes=new byte[1024*8];
for (FileInputStream in : list) {
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
in.close();
}
out.close();
}
}
操作字符数组:
public class MyTest {
public static void main(String[] args) throws IOException {
// b:
// 操作字符数组
// CharArrayWrite
// CharArrayReader
CharArrayWriter writer = new CharArrayWriter();
writer.write("西部开源教育科技有限公司");
writer.write("简简单单,只为教育");
char[] chars = writer.toCharArray();
String s = String.valueOf(chars);
System.out.println(s);
String s1 = writer.toString();
System.out.println(s1);
}
}
操作字符串:
public class MyTest2 {
public static void main(String[] args) {
// StringWriter
// StringReader
StringWriter stringWriter = new StringWriter();
stringWriter.write("asdfasdfasf");
stringWriter.write("asdfasdfasf");
String s = stringWriter.toString();
System.out.println(s);
}
}
3.打印流的概述和特点以及作为Writer的子类使用)
1.打印流的概述
通过API查看
字节流打印流
字符打印流
2.打印流的特点
a: 打印流只能操作目的地,不能操作数据源(不能进行读取数据)
- b: 可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型- c: 如果我们启用自动刷新,那么在调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
/**
通过以下构造创建对象 能够启动自动刷新 然后调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
* public PrintWriter(OutputStream out, boolean autoFlush) 启动 自动刷新
* public PrintWriter(Writer out, boolean autoFlush) 启动自动刷新
*/- d: 这个流可以直接对文件进行操作(可以直接操作文件的流: 就是构造方法的参数可以传递文件或者文件路径)
3.案例演示: PrintWriter作为Writer的子类使用
字节打印流:
public class MyTest {
public static void main(String[] args) throws IOException {
//打印流:单个的,没有成对出现,只能写数据,不能读数据
//字节打印流
// 自己创建的打印流,关联的是文件
PrintStream printStream = new PrintStream("hehe.text");
printStream.write("aaaa".getBytes());
printStream.write("\r\n".getBytes());
printStream.println("asfasdfasdfasdfffff");
printStream.print(true);
printStream.println(3.14);
printStream.close();
//System.out 返回的 这个字节打印流,关联的设备是屏幕
PrintStream out = System.out;
out.println(200);
}
}
4.PrintWriter实现自动刷新和换行
案例演示:PrintWriter实现自动刷新和换行
PrintWriter pw = new PrintWriter(new FileWriter("printWriter2.txt") , true) ;
pw.println(true) ;
pw.println(100) ;
pw.println("中国") ;
public class MyTest2 {
public static void main(String[] args) throws FileNotFoundException {
PrintWriter printWriter = new PrintWriter(new FileOutputStream("haha.txt"),true);
//如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。
//printWriter.write("asfasdfasdfasdf");
printWriter.flush();
printWriter.println("asdfasdfasdf");
printWriter.println("asdfasdfasdfasdf");
//printWriter.flush();
printWriter.close();
}
}
5.打印流复制文本文件
案例演示: 打印流复制文本文件
分析:
- 这个打印流只能进行写数据,不能进行读取数据,
那么我们应该找一个可以读取文本文件中的的数据的流对象进行读取操作.
- 而我们非常喜欢高效的流对象,于是我们可以使用BufferedReader进行读取数据.
public class MyTest3 {
public static void main(String[] args) throws IOException {
// A:
// 案例演示:
// 打印流复制文本文件
BufferedReader reader = new BufferedReader(new FileReader("haha.txt"));
PrintWriter printWriter = new PrintWriter(new FileOutputStream("ccc.txt"), true);
while (true){
String s = reader.readLine();
if (s == null) {
break;
}
printWriter.println(s);
}
reader.close();
printWriter.close();
}
}
6.标准输入输出流概述和输出语句的本质
标准输入输出流概述
在System这个类中存在两个静态的成员变量:
-- public static final InputStream in: 标准输入流, 对应的设备是键盘
- public static final PrintStream out: 标准输出流 , 对应的设备就是显示器
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的孙子类FilterOutputStream 的子类.
案例演示: 输出语句的本质
7.二种方式实现键盘录入
1.Scanner
2.BufferedReader的readLine方法。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Scanner类关联文件:
public class MyTest2 {
public static void main(String[] args) throws FileNotFoundException {
// 构造方法摘要
// Scanner(File source)
// 构造一个新的 Scanner,它生成的值是从指定文件扫描的。
Scanner scanner = new Scanner(new File("haha.txt"));
while (scanner.hasNextLine()) {
String s = scanner.nextLine();
System.out.println(s);
}
scanner.close();
}
}
Scanner类寻找指定内容:
public class MyTest3 {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("haha.txt"));
// String findInLine (Pattern pattern)
// 试图在忽略分隔符的情况下查找下一个指定模式。
String inLine = scanner.findInLine("\\b[a-z]{3}\\b");
System.out.println(inLine);
scanner.close();
}
}
8.输出语句用字符缓冲流改进
A:案例演示: 输出语句用字符缓冲流改进
/**
* 获取System下的in成员变量
*/
InputStream in = System.in ;
/**
* in是一个字节输入流对象,那么我们就可以通过这个字节输入流对象进行读取键盘录入的数据.
* 那么我们既然要读取数据,之前我们讲解了两种读取数据的方式:
* 1. 一次读取一个字节
* 2. 一次读取一个字节数组
* 那么我们在这个地方使用那种读取方式. 经过分析,这两种读取方式都不太合适.因为数据是客户通过键盘录入
* 进来的,而我们希望直接读取一行数据. 而既然要读取一行数据,那么我们就需要使用readLine方法,而这个方法
* 是属于BufferedReader的方法,而我们就需要创建一个BufferedReader对象进行读取数据.而我们这in有属于
* 字节流,而创建BufferedReader对象的时候需要一个字符流,而我们就需要将这个字节流转换成字符流,那么既然
* 要对其进行转换,那么就需要使用转换流. 需要使用InputStreamReader
*/
BufferedReader流实现键盘录入:
public class MyTest {
public static void main(String[] args) throws IOException {
// Scanner scanner = new Scanner(System.in);
//键盘录入的第二种方式
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
System.out.println("请输入数据");
String s = reader.readLine();
if("886".equals(s)){
break;
}
System.out.println(s);
}
}
}
9.随机访问流概述和写出数据
1.随机访问流概述
RandomAccessFile概述 最大特点 能读能写
RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
支持对随机访问文件的读取和写入。RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针
2.案例演示: 随机访问流写出数据
10.随机访问流读取数据和操作文件指针
public class MyTest4 {
public static void main(String[] args) throws IOException {
// A:
// 随机访问流概述
// RandomAccessFile概述 最大特点 能读能写
// RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
// 支持对随机访问文件的读取和写入。
//
// RandomAccessFile的父类是Object, 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
// 我们可以通过getFilePointer方法获取文件指针, 并且可以通过seek方法设置文件指针
//writeData();
//你怎么写的你就怎么读
RandomAccessFile out = new RandomAccessFile("e.txt", "rw");
int i = out.readInt();
//获取文件指针位置
long filePointer = out.getFilePointer();
System.out.println("文件指针位置:"+filePointer); //4
boolean b = out.readBoolean();
filePointer = out.getFilePointer();
System.out.println("文件指针位置:" + filePointer); //5
double v = out.readDouble();
filePointer = out.getFilePointer();
System.out.println("文件指针位置:" + filePointer); //13
String s = out.readUTF();
filePointer = out.getFilePointer();
System.out.println("文件指针位置:" + filePointer);//21
System.out.println(i);
System.out.println(b);
System.out.println(v);
System.out.println(s);
//设置文件指针的位置
out.seek(13);
s = out.readUTF();
filePointer = out.getFilePointer();
System.out.println("文件指针位置:" + filePointer);//21
System.out.println(s);
}
private static void writeData() throws IOException {
RandomAccessFile out= new RandomAccessFile("e.txt", "rw");
out.writeInt(100);
out.writeBoolean(true);
out.writeDouble(3.2);
out.writeUTF("呵呵");
out.close();
}
}
11.序列化流和反序列化流的概述和使用
1.序列化流的概述
所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象 要重写Serializable 接口才能被序列化
反序列化:就是把文件中存储的对象以流的方式还原成对象
序列化流: ObjectOutputStream
反序列化流: ObjectInputStream像这样一个接口中如果没有方法,那么这样的接口我们将其称之为标记接口(用来给类打标记的,相当于猪肉身上盖个章)
一个对象可以被序列化的前提是这个对象对应的类必须实现Serializable接口
B:案例演示: 对象序列化和反序列化的基本使用
序列化和反序列化
序列化:把对象转换为字节序列的过程称为对象的序列化.
反序列化:把字节序列恢复为对象的过程称为对象的反序列化.
什么时候需要用到序列化和反序列化呢?
当我们只在本地JVM里运行下Java实例, 这个时候是不需要什么序列化和反序列化的, 但当我们需要将内存中的对象持久化到磁盘, 数据库中时,
当我们需要与浏览器进行交互进行网络传输时, 这个时候就需要序列化和反序列化了.
只要我们对内存中的对象进行持久化或网络传输, 这个时候都需要序列化和反序列化.
12.如何解决序列化时候的黄色警告线问题
实现Serializable接口, 为什么还要显示指定serialVersionUID的值?
如果不显示指定serialVersionUID, JVM在序列化时会根据属性自动生成一个serialVersionUID, 然后与属性一起序列化, 再进行持久化或网络传输.
在反序列化时, JVM会再根据属性自动生成一个新版serialVersionUID, 然后将这个新版serialVersionUID与序列化时生成的旧版serialVersionUID进行比较, 如果相同则反序列化成功, 否则报错.
如果显示指定了serialVersionUID, JVM在序列化和反序列化时仍然都会生成一个serialVersionUID, 但值为我们显示指定的值, 这样在反序列化时新旧版本的serialVersionUID就一致了.
在实际开发中, 不显示指定serialVersionUID的情况会导致什么问题? 如果我们的类写完后不再修改, 那当然不会有问题, 但这在实际开发中是不可能的, 我们的类会不断迭代, 一旦类被修改了, 那旧对象反序列化就会报错. 所以在实际开发中, 我们都会显示指定一个serialVersionUID, 值是多少无所谓, 只要不变就行.
Student类中定义一个标间接口:
//Serializable 接口中没有任何方法,这种接口我们叫做标记接口,给类打个标记,让JVM支持某种操作
//Cloneable 接口中没有任何方法,这种接口我们叫做标记接口
public class Student implements Serializable{
// 最好,显示指定serialVersionUID,值你随便给一个
private static final long serialVersionUID = -8959141644637249870L;
public String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
存入一个对象:
public class MyTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化:把java对象的字节数据保存到硬盘上
// 反序列化:java对象的字节数据读取回内存
// void writeObject (Object obj)
// 将指定的对象写入 ObjectOutputStream。
//writeData();
readData();
}
private static void readData() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
//反序列化
Student object = (Student) in.readObject();
System.out.println(object);
}
private static void writeData() throws IOException {
Student student = new Student("张三",23);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
//序列化
out.writeObject(student);
out.close();
}
}
存入两个对象:
public class MyTest2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化:把java对象的字节数据保存到硬盘上
// 反序列化:java对象的字节数据读取回内存
// void writeObject (Object obj)
// 将指定的对象写入 ObjectOutputStream。
//writeData();
readData();
}
private static void readData() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
//反序列化
Student object = (Student) in.readObject();
System.out.println(object);
object = (Student) in.readObject();
System.out.println(object);
}
private static void writeData() throws IOException {
Student student = new Student("张三",23);
Student student2 = new Student("李四", 24);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
//序列化
out.writeObject(student);
out.writeObject(student2);
out.close();
}
}
把两个对象存入集合中,读的时候可以根据索引读:
public class MyTest3 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化:把java对象的字节数据保存到硬盘上
// 反序列化:java对象的字节数据读取回内存
// void writeObject (Object obj)
// 将指定的对象写入 ObjectOutputStream。
//writeData();
readData();
}
private static void readData() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
//反序列化
ArrayList<Student> list = (ArrayList<Student>) in.readObject();
System.out.println(list.get(1));
}
private static void writeData() throws IOException {
Student student = new Student("张三",23);
Student student2 = new Student("李四", 24);
ArrayList<Student> students = new ArrayList<>();
students.add(student);
students.add(student2);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
//序列化
out.writeObject(students);
out.close();
}
}
13.如何让对象的成员变量不被序列化
案例演示: 如何让对象的成员变量不被序列化
使用transient关键字声明不需要序列化的成员变量private transient int age ;// 可以阻止成员变量的序列化使用transient
注意:静态变量也不会序列化,因为序列化是针对对象而言的, 而static属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化.
14.Properties的概述和作为Map集合的使用
1.Properties的概述
查看API
Properties 类表示了一个持久的属性集。
Properties 可保存在流中或从流中加载。
属性列表中每个键及其对应值都是一个字符串。
Properties父类是Hashtable
- 属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型
2.案例演示: Properties作为Map集合的使用
普通方式把双列集合放到文件中:
public class MyTest {
public static void main(String[] args) throws IOException {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("username","zhangsan");
map.put("password","123456");
//把双列集合中的数据存到文件中
//username=zhangsan
//password=123456
BufferedWriter writer = new BufferedWriter(new FileWriter("user.properties"));
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
try {
writer.write(key+"="+value);
writer.newLine();
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
writer.close();
}
}
public class MyTest2 {
public static void main(String[] args) throws IOException {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
BufferedReader reader = new BufferedReader(new FileReader("user.properties"));
while (true){
String s = reader.readLine();
if (s == null) {
break;
}
String[] split = s.split("=");
map.put(split[0],split[1]);
}
System.out.println(map);
}
}
15.Properties的特殊功能使用
1.Properties的特殊功能
public Object setProperty(String key,String value)
public String getProperty(String key)
public Set<String> stringPropertyNames()
2.案例演示: Properties的特殊功能
public class MyTest3 {
public static void main(String[] args) {
//Properties extends Hashtable<Object,Object>
Properties properties = new Properties();
//properties.put("name", "zhangsan");
//默认键值存为String
properties.setProperty("name","zhangsan");
String name = properties.getProperty("name");
//第二个参数,是默认值,如果键没有找到对应的值,返回默认值
String property = properties.getProperty("name2", "lisi");
}
}
16.Properties的load()和store()功能
1.Properties的load()和store()功能
Properties和IO流进行配合使用:
- public void load(Reader reader): 读取键值对数据把数据存储到Properties中- public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释
2.案例演示
Properties的load()和store()功能
store():
public class MyTest4 {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.setProperty("username","王老虎");
properties.setProperty("password","654321");
//键=值
//把集合中的键值数据保存到文件中
properties.store(new FileWriter("user.properties"),"用户的信息");
}
}
load():
public class MyTest5 {
public static void main(String[] args) throws IOException {
//读取配置文件,文件中的键值是=号拼接的
Properties properties = new Properties();
properties.load(new FileReader("user.properties"));
System.out.println(properties);
}
}
17.判断文件中是否有指定的键如果有就修改值的
案例演示
需求:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。
请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”分析:
- a: 把文本文件中的数据加载到Properties集合中
- b: 判断这个集合中是否有"lisi"这个键
- 如果有直接修改其值为100
- c: 把集合中的数据再次存储到文本文件中
public class MyTest2 {
public static void main(String[] args) throws IOException {
//我有一个配置文件,数据是键=值形式,让你判断他有没有lisi这个键,如果有把他的值改成100
Properties properties = new Properties();
properties.load(new FileInputStream("user.properties"));
if (properties.containsKey("lisi")) {
properties.setProperty("lisi","王五");
properties.store(new FileWriter("user.properties"),null);
}else{
System.out.println("没有这个键");
}
}
}
18.SequenceInputStream
1.案例需求:将a.txt和b.txt两个文本文件的内容合并到c.txt
2.案例需求:采用SequenceInputStream来改进
3.作业:将一个music.mp3文件,拆分成多个小文件,再将多个小文件,合并成一个mp3文件
4.SequenceInputStream
表示其他输入流的逻辑串联。
它从输入流的有序集合开始,
并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,
依次类推,直到到达包含的最后一个输入流的文件末尾为止
a:构造方法
SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),
以提供从此 SequenceInputStream 读取的字节。
b:构造方法
SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
多个文件合并:
采用这个构造方法SequenceInputStream(InputStream s1, InputStream s2)
public class MyTest {
public static void main(String[] args) throws IOException {
// SequenceInputStream
// SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,
// 接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
// SequenceInputStream(InputStream s1, InputStream s2)
// 通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
FileInputStream in1 = new FileInputStream("叶丽仪 - 新上海滩.mp3");
FileInputStream in2 = new FileInputStream("烟花易冷Live_林志炫.mp3");
SequenceInputStream in = new SequenceInputStream(in1, in2);
FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\歌曲大连唱3.mp3");
int len = 0;
byte[] bytes = new byte[1024 * 8];
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
in.close();
out.close();
}
}
多个文件合并:
采用这个构造方法SequenceInputStream(Enumeration<? extends InputStream> e)
public class MyTest2 {
public static void main(String[] args) throws IOException {
FileInputStream in1 = new FileInputStream("叶丽仪 - 新上海滩.mp3");
FileInputStream in2 = new FileInputStream("烟花易冷Live_林志炫.mp3");
FileInputStream in3 = new FileInputStream("许巍 - 曾经的你.mp3");
FileInputStream in4 = new FileInputStream("许巍 - 蓝莲花.mp3");
// SequenceInputStream(Enumeration < ? extends InputStream > e)
// 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
Vector<FileInputStream> vector = new Vector<>();
vector.add(in1);
vector.add(in2);
vector.add(in3);
vector.add(in4);
Enumeration<FileInputStream> elements = vector.elements();
SequenceInputStream in = new SequenceInputStream(elements);
FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\歌曲大连唱4.mp3");
int len = 0;
byte[] bytes = new byte[1024 * 8];
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
in.close();
out.close();
}
}
19.把一个文件复制多份
public class MyTest {
public static void main(String[] args) throws IOException {
//把一个文件复制多份
RandomAccessFile in = new RandomAccessFile("C:\\Users\\ShenMouMou\\Desktop\\mv.jpg","rw");
byte[] bytes = new byte[1024 * 8];
int len=0;
for (int i = 1; i <=10; i++) {
FileOutputStream out = new FileOutputStream(new File("C:\\Users\\ShenMouMou\\Desktop\\", i + "mv.jpg"));
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
out.close();
in.seek(0);
}
in.close();
}
}
20.将一个music.mp3文件, 拆分成多个小文件, 再将多个小文件, 合并成一个mp3文件
*要求1M拆一份 比如 music.mp3文件 5.4M 拆分成六分 最后一份 0.4M
*再把这些零碎文件合并回去。
public class MyTest3 {
public static void main(String[] args) throws IOException {
//chaiFen();
//迭代器合并方式
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\music");
File[] files = file.listFiles();
Vector<FileInputStream> vector = new Vector<>();
for (File f : files) {
FileInputStream minIn = new FileInputStream(f);
vector.add(minIn);
}
System.out.println(vector);
Enumeration<FileInputStream> elements = vector.elements();
SequenceInputStream in = new SequenceInputStream(elements);
FileOutputStream out = new FileOutputStream(new File(file, "人生.mp3"));
byte[] bytes = new byte[1024 * 8];
int len = 0;
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
out.close();
in.close();
//删除零碎的文件
File[] files2 = file.listFiles();
for (File f1: files2) {
if(f1.length()<=1024*1024&&f1.getName().endsWith(".mp3")){
f1.delete();
}
}
}
private static void chaiFen() throws IOException {
//把文件拆分成 1M 1份,最后一份有多少算多少
FileInputStream in = new FileInputStream("人生.mp3");
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\music");
if (!file.exists()) {
file.mkdirs();
}
byte[] bytes = new byte[1024 * 1024];
int len = 0;
int i = 1;
while ((len = in.read(bytes)) != -1) {
FileOutputStream out = new FileOutputStream(new File(file, (i++) + ".mp3"));
out.write(bytes, 0, len);
out.close();
}
in.close();
}
}