文章目录
数据输入输出流的概述和使用:
- 最大特点:能够读写基本数据类型
- 数据输入流:DataInputStream
- 数据输出流:DataOutputStream
- 示例:
注意:public class MyTest { public static void main(String[] args) throws IOException { //数据输入输出流:这对流,最大的特点就是能够读写基本数据类型 // DataInputStream // DataOutputStream write(); //你怎么写的就怎么读取,顺序不要乱 DataInputStream dis = new DataInputStream(new FileInputStream("a.txt")); boolean b = dis.readBoolean(); double v = dis.readDouble(); int i = dis.readInt(); String s = dis.readUTF(); System.out.println(b); System.out.println(v); System.out.println(i); System.out.println(s); } private static void write() throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.txt")); dos.writeBoolean(true); dos.writeDouble(3.14); dos.writeInt(500); dos.writeUTF("一句话"); dos.close(); } } ------------- 输出: true 3.14 500 一句话
a. 所写的文件都是乱码,不具有可读性(利用配套的读取方法来读取数据)
b. 写入的顺序是什么,读取的顺序也必须是什么!顺序不能乱!
内存操作流的概述和使用:
-
特点:
a. 这个流不关联任何文件,只在内存中操作数据
b. 内存操作流,自己在内存中维护着一个缓冲区,我们可以往它维护的缓冲区中不断写入数据,也可以从缓冲区中取出我们写入的数据。 -
内存操作流的概述:
a:操作字节数组
ByteArrayOutputStream
ByteArrayInputStream
此流关闭无效,所以无需关闭
b:操作字符数组
CharArrayWrite
CharArrayReader
c:操作字符串
StringWriter
StringReader
-
案例演示: 内存操作流的使用(操作字节数组!)
public class MyTest2 { public static void main(String[] args) throws IOException { /* ByteArrayOutputStream 此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray () 和 toString () 获取数据。内存操作流无需关闭*/ //关闭 ByteArrayOutputStream 无效 //创建出内存操作流 他维护着一个字节数组来充当缓冲区 ByteArrayOutputStream bos = new ByteArrayOutputStream(); bos.write("好好学习".getBytes()); bos.write("天天向上".getBytes()); bos.write("爱生活".getBytes()); bos.write("爱Java".getBytes()); byte[] bytes = bos.toByteArray(); String s = new String(bytes); System.out.println(s); String s2 = bos.toString(); System.out.println(s2); read(bytes); } private static void read(byte[] bytes) throws IOException { /* ByteArrayInputStream( byte[] buf) 创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。*/ ByteArrayInputStream bis = new ByteArrayInputStream(bytes); --------------------------------- int read = bis.read(); int read1 = bis.read(); int read2 = bis.read(); byte[] bytes1 = {(byte) read, (byte) read1, (byte) read2}; 三个字节构成一个汉字(UTF-8) String s = new String(bytes1); 默认使用UTF-8进行编码! System.out.println(s); 一个汉字:好 -------------------------------- byte[] bytes2 = new byte[1024]; int len = bis.read(bytes2); String s1 = new String(bytes2, 0, len); System.out.println(s1); } } ------------ 输出: 好好学习天天向上爱生活爱Java 好好学习天天向上爱生活爱Java 好 好学习天天向上爱生活爱Java
-
案例演示: 内存操作流的使用(操作字符数组!)
public class MyTest3 { public static void main(String[] args) throws IOException { /* b: 操作字符数组 CharArrayWrite CharArrayReader*/ CharArrayWriter charArrayWriter = new CharArrayWriter(); charArrayWriter.write("abc"); charArrayWriter.write("abc"); charArrayWriter.write("abc"); charArrayWriter.write("abc"); charArrayWriter.write("abc"); /* char[] chars = charArrayWriter.toCharArray(); String s = String.valueOf(chars); System.out.println(s); */ String s = charArrayWriter.toString(); } }
-
案例演示:内存操作流的使用(操作字符串!)
public class MyTest4 { public static void main(String[] args) { /* c: 操作字符串 StringWriter StringReader*/ StringWriter stringWriter = new StringWriter(); stringWriter.write("abc"); stringWriter.write("abc"); stringWriter.write("abc"); stringWriter.write("abc"); stringWriter.write("abc"); String s = stringWriter.toString(); } }
-
案例:(拼接多首歌曲为一首)
思想:利用内存操作流作为一个中转进行存储!
(可以把内存操作流当做一个内存虚拟化后的文件,在这个文件中进行处理操作,最后再把这个操作完以后的结果输出到真实的文件中去!)
这个应该也可以把这些从文件中读取到的Byte数组存储到ArrayList中去,然后最后把ArrayList中的结果输出到文件中去。public class MyTest { public static void main(String[] args) throws IOException { //需求:将多个mp3文件,拼接成一个mp3文件 // ByteArrayOutputStream // ByteArrayInputStream //首先,按照字节读取的方法将文件读取出来。 FileInputStream song1_in = new FileInputStream("许巍 - 曾经的你.mp3"); FileInputStream song2_in = new FileInputStream("许巍 - 蓝莲花.mp3"); //读取其中的字节到内存缓冲区中 ByteArrayOutputStream bos = new ByteArrayOutputStream(); outputToBos(song1_in, bos); outputToBos(song2_in, bos); //将内存缓冲区中的数据读出,并且输出到目标文件中去: FileOutputStream song_out = new FileOutputStream("合并.mp3"); outputToFile(bos.toByteArray(),song_out); } private static void outputToFile(byte[] toByteArray, FileOutputStream song_out) throws IOException { byte[] bytes = new byte[1024 * 8]; ByteArrayInputStream bis = new ByteArrayInputStream(toByteArray); int len =0; while((len=bis.read(bytes))!=-1){ song_out.write(bytes,0,len); } song_out.close(); } private static void outputToBos(FileInputStream song_in, ByteArrayOutputStream bos) throws IOException { byte[] bytes = new byte[1024 * 8]; int len =0 ; while((len=song_in.read(bytes))!=-1){ bos.write(bytes,0,len); } song_in.close(); } }
打印流的概述和特点:
-
概述:字节流打印流、字符打印流。
PrintStream 字节流打印流。 PrintWriter 字符打印流。
-
关联文件:(相当于写文件)
-
关联屏幕:(往屏幕中输出!)
-
打印流的特点:
a:打印流只能操作目的地,不能操作数据源(不能进行读取数据)
b:可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型 -
示例:(字节流打印流)
public class MyTest { public static void main(String[] args) throws IOException { //打印流:他只关联目的地,不关联源文件。直白点,他只能输出,不能读取 /* PrintStream(String fileName) 创建具有指定文件名称且不带自动行刷新的新打印流。*/ //通过创建得来的字节打印流,关联的是文件,那么你是往文件中打印数据 PrintStream printStream = new PrintStream(new File("b.txt")); printStream.write("曾梦想仗剑走天涯,看一看世界的繁华".getBytes()); printStream.write("\r\n".getBytes()); printStream.println(true); printStream.println("曾梦想仗剑走天涯,看一看世界的繁华"); printStream.close(); //System.out 获取出的这个字节打印流,关联的设备是屏幕 PrintStream out = System.out; //关联屏幕 out标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器 out.write("abc".getBytes()); out.print(20000); out.println(300000); System.out.println(); } } ------------- 输出: abc20000300000
-
示例:(字符流打印流)
public class MyTest2 { public static void main(String[] args) throws FileNotFoundException { // PrintWriter 字符打印流 PrintWriter printWriter = new PrintWriter("c.txt"); printWriter.write("abc"); printWriter.print(100); printWriter.println("abc"); printWriter.flush(); printWriter.close(); } }
-
开启自动刷新:
public class MyTest3 { public static void main(String[] args) throws FileNotFoundException { /* PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。 如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作 */ //参数2 是否开启自动刷新 PrintWriter printWriter = new PrintWriter(new FileOutputStream("d.txt"), true); //printWriter.write("abc"); printWriter.println("abc"); printWriter.println("abc"); printWriter.flush(); // 相当于不用写这个语句了! printWriter.close(); } }
-
示例:(打印流复制文本文件)
-
分析:
a. 这个打印流只能进行写数据,不能进行读取数据,
b. 那么我们应该找一个可以读取文本文件中的的数据的流对象进行读取操作.
c. 而我们非常喜欢高效的流对象,于是我们可以使用BufferedReader进行读取数据.public class MyTest4 { public static void main(String[] args) throws IOException { /* A: 案例演示: 打印流复制文本文件*/ // BufferedReader bfr = new BufferedReader(new FileReader("MyTest.java")); PrintWriter printWriter = new PrintWriter(new FileOutputStream("MyTest222.java"),true); String line=null; while ((line=bfr.readLine())!=null){ printWriter.println(line); //printWriter.flush(); } bfr.close(); printWriter.close(); } }
-
案例:(将一首歌曲复制五次!)
public class MyTest2 { public static void main(String[] args) throws IOException { //待复制的文件。 int[] ints = {1, 2, 3, 4, 5}; // for (int i : ints) { // FileInputStream file_in = new FileInputStream("合并.mp3"); // FileOutputStream file_out = new FileOutputStream("合并" + i + ".mp3"); // byte[] bytes = new byte[1024 * 8]; // int len = 0; // while((len=file_in.read(bytes))!=-1){ // file_out.write(bytes,0,len); // } // file_out.close(); // file_in.close(); // } // // //通过打印流复制: // for (int i : ints) { // FileInputStream file_in = new FileInputStream("合并.mp3"); // PrintStream printStream = new PrintStream("result"+i+".mp3"); // byte[] bytes = new byte[1024 * 8]; // int len = 0; // while((len=file_in.read(bytes))!=-1){ // printStream.write(bytes,0,len); // } // printStream.close(); // file_in.close(); // } // 将数据保存下来,直接复制即可,不用每次都从文件中读取。 FileInputStream file_in = new FileInputStream("合并.mp3"); HashMap<byte[], Integer> map = new HashMap<>(); // ArrayList<byte[]> list = new ArrayList<>(); int len= 0; byte[] bytes =null; while(true){ bytes = new byte[1024 * 8]; len=file_in.read(bytes); if(len == -1){ break; }else{ map.put(bytes,len); } } file_in.close(); Set<Map.Entry<byte[], Integer>> entries = map.entrySet(); FileOutputStream file_out = new FileOutputStream("test.mp3"); for (Map.Entry<byte[], Integer> entry : entries) { file_out.write(entry.getKey(),0,entry.getValue()); } file_out.close(); } }
标准输入输出流概述和输出语句的本质
- 标准输入输出流概述
在System这个类中存在两个静态的成员变量:
System.in的类型是InputStream.public static final InputStream in: 标准输入流, 对应的设备是键盘 public static final PrintStream out: 标准输出流 , 对应的设备就是显示器
System.out的类型是PrintStream是OutputStream的孙子类FilterOutputStream 的子类.
二种方式实现键盘录入:
- 第一种:Scanner
- 第二种:BufferedReader的readLine方法。
分析过程:
示例://获取System下的in成员变量 InputStream in = System.in ; /** * in是一个字节输入流对象,那么我们就可以通过这个字节输入流对象进行读取键盘录入的数据. * 那么我们既然要读取数据,之前我们讲解了两种读取数据的方式: * 1. 一次读取一个字节 * 2. 一次读取一个字节数组 * 那么我们在这个地方使用那种读取方式. 经过分析,这两种读取方式都不太合适.因为数据是客户通过键盘录入 * 进来的,而我们希望直接读取一行数据. 而既然要读取一行数据,那么我们就需要使用readLine方法,而这个方法 * 是属于BufferedReader的方法,而我们就需要创建一个BufferedReader对象进行读取数据.而我们这in有属于 * 字节流,而创建BufferedReader对象的时候需要一个字符流,而我们就需要将这个字节流转换成字符流,那么既然 * 要对其进行转换,那么就需要使用转换流. 需要使用InputStreamReader */
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- 示例:
public class MyTest { public static void main(String[] args) throws IOException { //键盘录入的第二种方式 //Scanner scanner = new Scanner(System.in); //System.in 这个参数其实是对应 的 键盘 //从文件扫描 //Scanner scanner = new Scanner(new FileInputStream("a.txt")); BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); while (true){ System.out.println("请输入数据"); String s = bfr.readLine(); if("886".equals(s)){ //自定义一个结束标记 break; } System.out.println(s); } } } -------------- 输出: 请输入数据 123 123 请输入数据 886
随机访问流:
-
特点:
a. 既能读又能写,在一个该类的对象中即可实现(其他流都必须是成对的方法)。
b. 文件指针系统(参考上课所述!),能够重置文件的指针到相应的位置去! -
概述:
a. RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
支持对随机访问文件的读取和写入。
b. RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
c. 我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针。 -
示例:(随机访问流读取数据和操作文件指针)
public class MyTest { public static void main(String[] args) throws IOException { //RandomAccessFile 随机访问流 /* //RandomAccessFile 此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针; 指针开始读取字节,并随着对字节的读取而前移此文件指针。*/ /* 构造方法摘要 RandomAccessFile(File file, String mode) 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。*/ //writeData(); readData(); } private static void writeData() throws IOException { RandomAccessFile raf = new RandomAccessFile("e.txt", "rw");//rw 表示可读可写 raf.writeBoolean(true); raf.writeDouble(3.14); raf.writeInt(200); raf.writeUTF("呵呵"); raf.close(); readData(); } private static void readData() throws IOException { //怎么写的怎么读,顺序不要乱 RandomAccessFile raf = new RandomAccessFile("e.txt", "rw");//rw 表示可读可写 boolean b = raf.readBoolean(); //获取文件指针的位置 long filePointer = raf.getFilePointer(); System.out.println(filePointer);//1 double v = raf.readDouble(); filePointer = raf.getFilePointer(); System.out.println(filePointer);//9 int i = raf.readInt(); filePointer = raf.getFilePointer(); System.out.println(filePointer);//13 String s = raf.readUTF(); filePointer = raf.getFilePointer(); System.out.println(filePointer);//19+2 System.out.println(b); System.out.println(v); System.out.println(i); System.out.println(s); //我把呵呵在读出来一遍 raf.seek(13); String s1 = raf.readUTF(); System.out.println(s1); } } ----------- 输出: 1 9 13 21 true 3.14 200 呵呵 呵呵
-
示例:(把一首歌复制5份!,利用指针重定位从而避免重复读取的情况!)
private static void randomStreamMethod() throws IOException { RandomAccessFile in = new RandomAccessFile("合并.mp3", "rw"); byte[] bytes = new byte[1024 * 8]; int len =0; for (int i = 0; i < 5; i++) { RandomAccessFile out = new RandomAccessFile(i + "合并.mp3", "rw"); while ((len=in.read(bytes))!=-1){ out.write(bytes,0,len); } out.close(); in.seek(0); } in.close(); }
-
断点下载:
public class MyTest4 { public static void main(String[] args) throws IOException { RandomAccessFile in = new RandomAccessFile("许巍 - 蓝莲花.mp3", "rw"); File mbFile = new File("许巍 - 蓝莲花4444.mp3"); RandomAccessFile out = new RandomAccessFile(mbFile, "rw"); int len=0; byte[] bytes = new byte[1024]; int i=1; try { while ((len = in.read(bytes)) != -1) { i++; out.write(bytes, 0, len); if(i>=2500){ //模拟下载出现断连的情况! System.out.println(1/0); } } }catch (Exception e){ e.printStackTrace(); long filePointer = in.getFilePointer(); //获取文件指针的位置 System.out.println(filePointer); PrintWriter printWriter = new PrintWriter(new File("ls.txt")); printWriter.println(filePointer); //将指针的数值写入到文件中进行保存!!! printWriter.flush(); printWriter.close(); } in.close(); out.close(); } } ------- 此时:文件 ls.txt中记录的是一个数字(filePointer的指向位置)为:2558976。 许巍 - 蓝莲花4444.mp3的文件大小为:2.44 MB (2,558,976 字节)
然后,利用刚才保存的文件重新读取回指针的位置,将指针指向该位置后继续下载:
public class MyTest5 { public static void main(String[] args) throws IOException { RandomAccessFile in = new RandomAccessFile("许巍 - 蓝莲花.mp3", "rw"); File mbFile = new File("许巍 - 蓝莲花4444.mp3"); RandomAccessFile out = new RandomAccessFile(mbFile, "rw"); //第二次来复制了 String s = new BufferedReader(new FileReader("ls.txt")).readLine(); long len2 = Long.parseLong(s); if(mbFile.exists()&&mbFile.length()==len2){ System.out.println("已经将指针指向为:"+len2); in.seek(len2); out.seek(len2); }else{ in.seek(0);//设置文件指针的位置 out.seek(0); } int len = 0; byte[] bytes = new byte[1024]; int i = 1; try { while ((len = in.read(bytes)) != -1) { //i++; out.write(bytes, 0, len); //if (i >= 2500) { // System.out.println(1 / 0); //} } } catch (Exception e) { e.printStackTrace(); long filePointer = in.getFilePointer(); //获取文件指针的位置 System.out.println(filePointer); PrintWriter printWriter = new PrintWriter(new File("ls.txt")); printWriter.println(filePointer); printWriter.flush(); printWriter.close(); } in.close(); out.close(); } } ------- 输出: 已经将指针指向为:2558976
最后:文件 许巍 - 蓝莲花4444.mp3的大小为:4.14 MB (4,343,818 字节),断点下载完毕!
序列化流和反序列化流的概述和使用:
- 序列化流的概述:
a. 所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象要重写Serializable 接口才能被序列化
b. 反序列化:就是把文件中存储的对象以流的方式还原成对象
c. Serializable : 这是一个标记接口,你要序列化该类对象,必须让这个类实现这个标记接口,序列化才被支持!序列化流: ObjectOutputStream 反序列化流: ObjectInputStream
- 案例演示:(对象序列化和反序列化的基本使用)
自定义序列化的对象:
主函数://Serializable 这是一个标记即可,你要序列化该类对象,必须让这个类实现这个标记接口,序列化才被支持 public class Student implements Serializable { private static final long serialVersionUID = 4709141572847639260L; //public static final long serialVersionUID = 42L; //手动写一个serialVersionUID private String name; //private transient int age; //transient 排除某个字段不要序列化 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; } }
public class MyTest { public static void main(String[] args) throws IOException, ClassNotFoundException { //序列化:将一个Java对象,保存到文件中 //反序列化:将文件中Java对象,再都会内存 wiriteObj(); readObj(); } private static void readObj() throws IOException, ClassNotFoundException { ObjectInputStream objIN = new ObjectInputStream(new FileInputStream("student.txt")); Object o = objIN.readObject(); Student student= (Student) o; System.out.println(student.getName()); System.out.println(student.getAge()); } private static void wiriteObj() throws IOException { Student student = new Student("张三", 23); // ObjectOutputStream 序列化流 写对象 // ObjectInputStream 反序列化流 读取对象 ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("student.txt")); objOut.writeObject(student); objOut.close(); } } ------------ 输出: 张三 23
- 如何解决序列化时候的黄色警告线问题?
a. 我们的一个类可以被序列化的前提是需要这个类实现Serializable接口,就需要给这个类添加一个标记.
b. 在完成序列化以后,序列化文件中还存在一个标记,然后在进行反序列化的时候,会验证这个标记和序列化前的标记是否一致,如果一致就正常进行反序列化,如果不一致就报错了.
c. 而现在我们把这个类做了修改,将相当于更改了标记,而导致这两个标记不一致,就报错了.
d. 解决问题: 只要让这个两个标记一致,就不会报错了吧
e. 怎么让这两个标记一致呢?
f. 不用担心,很简单,难道你们没有看见黄色警告线吗? alt+enter, 生成出来private static final long serialVersionUID = -7602640005373026150L;
- 如何让对象的成员变量不被序列化?
使用transient关键字声明不需要序列化的成员变量。如:class Student implement Serializable { ... private transient int age; //(排除某个字段不要被序列化) ... }
Properties 属性集合:
- 概述:
a. Properties 类表示了一个持久的属性集。
b. Properties 可保存在流中或从流中加载。
c. 属性列表中每个键及其对应值都是一个字符串。 - 特点:
a. 继承自HashTable,是一个双列集合。
b. 有自定义的存储的方法,只能存键和值都是字符串的。 - 示例:(Properties作为Map集合的使用)
public class MyTest { public static void main(String[] args) { //属性集合 //Properties 继承Hashtable 是一个双列集合 //规定键值都是字符串类型 Properties properties = new Properties(); /* properties.put("usename","张三"); 老方法 properties.put("password","123456"); 老方法 System.out.println(properties);*/ // System.out.println(properties.get("usename")); properties.setProperty("username", "张三"); //新方法 properties.setProperty("password", "123456"); //新方法 String username = properties.getProperty("username"); //当这个键对应的值得没找到,可以返回这个备用值,参数2 可以指定一个备用的值(很像Python中的字典的get方法!) String pwd = properties.getProperty("password","654321"); System.out.println(username); System.out.println(pwd); } }
- Properties的load()和store()功能:
- store()功能示例:
public class MyTest2 { public static void main(String[] args) throws IOException { Properties properties = new Properties(); properties.setProperty("username", "张三"); properties.setProperty("password", "123456"); // System.out.println(properties); //把属性集合中的键值对数据写入配置文件中保存 //参数2:是注释 一般给个null 写个默认注释 properties.store(new FileOutputStream("user.properties"),"hehehe"); 下面注释的部分相当于是手动来保存键值对! /* *//* username=张三 password=123456 *//* Set<Map.Entry<Object, Object>> entries = properties.entrySet(); FileOutputStream fileOutputStream = new FileOutputStream(new File("user.txt")); BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(fileOutputStream)); for (Map.Entry<Object, Object> entry : entries) { String key = (String) entry.getKey(); String value = (String) entry.getValue(); String data=key+"="+value; bos.write(data); bos.newLine(); bos.flush(); } bos.close(); fileOutputStream.close();*/ } }
- load()功能示例:
public class MyTest3 { public static void main(String[] args) throws IOException { //把配置文件中的键值对数据,再次都会属性集合中 //Properties 读取配置文件,对文件有要求,1.键值对,是 = 拼接 2.属性集合读取到的这个文件的后缀名是以.properties Properties properties = new Properties(); //读取配置文件 properties.load(new FileInputStream("user.properties")); System.out.println(properties); System.out.println(properties.getProperty("username")); } } --------- 输出: {password=123456, lisi=500, username=张三} 张三
顺序流SequenceInputStream:
-
概述:
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流(头部)读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。 -
示例:(将多首MP3文件合成为一首!)
public class MyTest { public static void main(String[] args) throws IOException { /*SequenceInputStream SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。*/ FileInputStream in1 = new FileInputStream("许巍 - 曾经的你.mp3"); FileInputStream in2 = new FileInputStream("许巍 - 蓝莲花.mp3"); FileInputStream in3 = new FileInputStream("许巍 - 蓝莲花.mp3"); FileOutputStream out = new FileOutputStream("gequ.mp3"); /* SequenceInputStream(InputStream s1, InputStream s2) 通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。*/ SequenceInputStream sequenceInputStream = new SequenceInputStream(in1, in2); SequenceInputStream sequenceInputStream1 = new SequenceInputStream(sequenceInputStream, in3); int len=0; byte[] bytes = new byte[1024 * 8]; while ((len=sequenceInputStream1.read(bytes))!=-1){ out.write(bytes,0,len); out.flush(); } out.close(); sequenceInputStream1.close(); } }
-
示例2:(将多首MP3文件合成为一首!,用可迭代对象进行传参!)
public class MyTest2 { public static void main(String[] args) throws IOException { FileInputStream in1 = new FileInputStream("许巍 - 曾经的你.mp3"); FileInputStream in2 = new FileInputStream("许巍 - 蓝莲花.mp3"); FileInputStream in3 = new FileInputStream("许巍 - 蓝莲花.mp3"); FileOutputStream out = new FileOutputStream("gequ2.mp3"); Vector<FileInputStream> vector = new Vector<>(); vector.add(in1); vector.add(in2); vector.add(in3); Enumeration<FileInputStream> elements = vector.elements(); /* SequenceInputStream(Enumeration < ? extends InputStream > e) 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。*/ SequenceInputStream sequenceInputStream1 = new SequenceInputStream(elements); int len = 0; byte[] bytes = new byte[1024 * 8]; while ((len = sequenceInputStream1.read(bytes)) != -1) { out.write(bytes, 0, len); out.flush(); } out.close(); sequenceInputStream1.close(); } }