黑马程序员——IO流

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
IO流
一、File类
   1File类:文件和目录路径名的抽象表现形式

     2、特点:1)用来将文件或文件夹封装成对象

                     2)方便于对文件与文件夹的属性信息进行操作

                     3File类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变

                     4File对象可以作为参数传递给流的构造函数

     3、构造方法:

           1)File(String pathname):根据指定的路径创建File对象。

           2)File(String parent, String child):根据指定的父文件夹和子文件或者文件夹创建File对象

           3)File(File parent, String child):根据指定的父文件夹对象和子文件或者文件夹创建File对象

     4、功能:

           1)创建文件:public boolean createNewFile():如果指定的文件不存在,就创建。如果存在,就不创建。
           2)创建文件夹:a、public boolean mkdir():创建指定的目录,如果存在,就不创建。
                                      b、public boolean mkdirs():创建指定的目录,如果存储,就不创建。这个时候,如果父目录不存在,它也会自动创建。

           3)删除功能:public boolean delete():既可以删除文件,也可以删除文件夹。取决于你使用的对象。
                注意:a、如果你删除的目录下还有内容,那么,必须先把所有内容删除完毕后,在删除目录。
                           b、java语言的删除不走回收站
           4)判断功能:a、boolean exists():判断file对象是否存在
                                  b、boolean isFile():判断file对象是否是文件
                                  c、boolean isDirectory():判断file对象是否是文件夹
                                  d、boolean isAbsolute():判断file对象是否是绝对路径
                                  e、boolean canRead():判断file对象是否可读
                                  f、 boolean canWrite():判断file对象是否可写
                                  g、boolean isHidden():判断file对象是否隐藏
           5)获取功能:a、String getAbsolutePath():绝对路径【绝对路径:以盘符开始的路径;相对路径:不以盘符开始的路径】
                                  b、String getPath():相对路径
                                  c、String getName():文件名称
                                  d、long length():文件大小,单位是字节
                                  e、long lastModified():上次修改时间的毫秒值。
           6)重要获取功能:a、public static File[] listRoots():列出可用的系统文件根目录
                                         b、public String[] list():返回的是指定目录下所有文件或者文件夹的名称数组
                                         d、public File[] listFiles():返回的是指定目录下所有文件或者文件夹对象数组
     5、功能练习:
package Test1;

import java.io.File;
import java.io.IOException;

public class FileTest {
	public static void main(String[] args) throws IOException{
		// 创建文件
		File file1 = new File("d:\\a.txt");
		System.out.println("createNewFile:" + file1.createNewFile());

		// 创建文件 忘了写路径名称了,以当前项目路径所在路径为父目录
		File file2 = new File("a.txt");
		System.out.println("createNewFile:" + file2.createNewFile());

		// 创建目录
		File file3 = new File("aaa");
		System.out.println("mkdir:" + file3.mkdir());

		// 如果目录过多,这样做就太麻烦。肿么办呢?
		File file4 = new File("bbb\\ccc");
		System.out.println("mkdirs:" + file4.mkdirs());

		// 创建文件
		File file5 = new File("b.txt");
		System.out.println("mkdir:" + file5.mkdir());
		System.out.println("-----------------");
// 判断功能
		System.out.println("exists:" + file1.exists());// true
		System.out.println("isFile:" + file1.isFile());// true
		System.out.println("isDirectory:" + file1.isDirectory());// false
		System.out.println("isAbsolute:" + file1.isAbsolute());// true
		System.out.println("canRead:" + file1.canRead());// true
		System.out.println("canWrite:" + file1.canWrite());// true
		System.out.println("isHidden:" + file1.isHidden());// false
		System.out.println("-----------------");
//获取功能:
		File file6 = new File("bbb\\ccc\\a.txt");

		System.out.println("getAbsolutePath:" + file6.getAbsolutePath());
		System.out.println("getPath:" + file6.getPath());
		System.out.println("getName:" + file6.getName());
		System.out.println("length:" + file6.length());
		System.out.println("lastModified:" + file6.lastModified());
		System.out.println("-----------------");

//删除功能
		File file7 = new File("a.txt");
		System.out.println("delete:" + file7.delete());

		// 需求:我要删除aaa
		File file8 = new File("aaa");
		System.out.println("delete:" + file8.delete());

		// 需求:我要删除bbb
		File file9 = new File("bbb");
		System.out.println("delete:" + file9.delete());
		
	}
}
运行结果:

二. 递归:
    1、归定义:方法定义调用方法本身的现象。
如:
public void show(){
	    show(); 
	}
2、注意事项:
a、递归一定要有出口。否则就会死递归。
b、递归的次数不要过多。否则内存溢出。
c、做递归的题思路 (1)找递归出口;(2)找递归规律
3、举例:用递归求n!
package Test1;

public class DiGuiTest {
	public static void main(String[] args) {
		System.out.println(DiGuiTest.jc(5));
	}
	public static int jc(int n) {
		if (n == 1) {
			// 出口
			return 1;
		} else {
			// 规律
			return n * jc(n - 1);
		}
	}
}
4、小案例1:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问:第二十个月的兔子对数为多少?
package Test1;

public class DiGuiTest {
	public static void main(String[] args) {
		System.out.println(DiGuiTest.sum(20));
	}
	private static int sum(int i) {
		if(i ==1){
			return 1;
		}else if(i==2){
			return 1;
		}else if(i==3){
			return 2;
		}else{
			return sum(i-3) +sum(i-2)+ sum(i-1);
		}
	}
}
5、小案例2:删除指定的目录。(目录是带有目录或者文件的)
package Test1;

import java.io.File;

public class DiGuiTest {
	public static void main(String[] args) {
		File f = new File("G:\\CopyFile");
		DiGuiTest.deleteFiles(f);
	}

	private static void deleteFiles(File file) {
		// 第1步封装文件夹
		File[] fileArray = file.listFiles();// 1,test_deleteFiles;
											// 2.1,aaa_deleteFiles;
											// 2.2,bbb_deleteFiles;

		if (fileArray != null) {
			// 如果封装的文件夹不为空,那么就进行遍历,获得每一个文件或文件夹
			for (File f : fileArray) {
				if (f.isDirectory()) {
					// 如果被封装文件夹的子文件还是个文件夹,那么继续封装起来进行判断
					deleteFiles(f);
				} else {
					// 如果被封装起来的子文件夹正好就是个文件,那么直接删除
					System.out.println(f.getName() + "***" + f.delete());
				}
			}
		}
		System.out.println(file.getName() + "***" + file.delete());
		// 如果文件夹为空,直接删除. 当if语句执行完时,就表示每次封装的目录下的文件被删除完毕。
	}
}
运行结果:

三. IO流的结构图:

1.字符流
(1)字符输出流
a.构造方法:
①.FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
②.FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
【在file对象的文件中追加写入数据,append是true的是后在指定的文件后面追加内容,false则是覆盖原来的内容】
③.FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。【名字是一个字符串的路径下文件,但是路径必须存在】
④.FileWriter(String fileName, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
【在字符串路径的文件中追加写入数据,append是true的是后在
                  ⑤.  FileWriter为什么没有无参构造方法?
      b.完成一个简单在指定文件中写入数据的操作的步骤:因为写数据的时候,一定要明确写道哪里去
①.创建字符输出流FileWriter对象(并且传入一个你要写入的位置)
FileWriter fw = new FileWriter("a.txt");
②.调用写数据的功能
fw.write("hello,io,我来了。祝你元旦快乐。");
③. 刷新缓冲区
fw.flush();
④.释放资源(jvm不会自动回收流的资源,除非你手动标记该流已成为垃圾)
fw.close();
d.flush()和close()的区别?
flush():只刷新缓冲区,流对象还可以继续使用。
close():先刷新缓冲区,在关闭流对象。流对象不可以继续被使用

(2)字符输入流

①、构造方法总结:

a、FileReader(File file) :在给定从中读取数据的 File[File必须一个明确的文件] 的情况下创建一个新 FileReader

b、FileReader(String fileName):在给定从中读取数据的文件名的情况下创建一个新FileReder

②、普通字符输入流读取数据步骤:
a、创建字符输入流对象(并且明确你要从哪个文件读数据)
FileReader fr = new FileReader("FileWriterDemo.java");
b、调用读取数据功能,并显示
int ch = 0;
while((ch=fr.read())!=-1){ //如果数据没有了,读取的时候,将返回-1
 //如果有数据则返回int类型(字符的int值),并自动移动到下一个数据位置等待读取
System.out.print((char) ch); }
c、释放资源
fr.close();
③、小案例:把当前项目下的FileWriterDemo.java文件拷贝到,G盘下并改名
package Test1;

import java.io.*;

public class FileTest {
	public static void main(String[] args) throws IOException {

		// 封装数据源
		FileReader fr = new FileReader("FileWriterDemo.java");
		// 封装目的地
		FileWriter fw = new FileWriter("G:\\Copy.java");

		// 读取数据
		int ch = 0;
		while ((ch = fr.read()) != -1) {
			fw.write(ch);
			System.out.print((char)ch);
			fw.flush();
		}
		// 释放资源
		fw.close();
		fr.close();
	}
}
运行结果如下:

(3)高效字符缓冲流:BufferedReader,BufferedWriter 
     BufferedReader,BufferedWriter是更高级的流,二者的源和目的地必须是字符输入流和字符输出流.如果把字符输入流做为BufferedReader流的源,把字符输出流作为BufferedWriter流的目的地,那么BufferedReader,BufferedWriter将有更强的读、写能力。

a、构造函数 BufferedReader(Reader in); BufferedWriter(Writer out); 

b、常用方法 

     int read();//读取单个字符 

      int read(char[] cbuf, int off, int len) //将字符读入数组的某一部分 

      String readLine()//读取一个文本行 

      void write(int c)//写入单个字符 

      void write(String s, int off, int len)//写入字符串的某一部分。 

      void write(char[] cbuf, int off, int len)//写入字符数组的某一部分 

      void newLine()//写入一个行分隔符 

c、使用方法 

BufferedReader ino=new BufferedReader(new FileReader("Student.txt"));//参数是字符流 

BufferedWriter outo=new BufferedWriter(new FileWrietr("Student.txt"));//参数是字符流

 d、小案例:

import java.io.*;
//编写一个程序,把指定目录下的所有的带.java文件都拷贝到另一个目录中,
//拷贝成功后,把后缀名是.java的改成.txt。
public class Test4 {
	static int count=0;
	public static void main(String[] args) throws IOException {
		File yfile=new File("F:\\");
		File mfile=new File("G:\\CopyFile");
		copyFile(yfile,mfile);
		System.out.println("共复制了:"+count+" 个文件");
	}
	public static void copyFile(File yfile,File mfile) throws IOException{
		if(yfile==null){
			System.out.println("源文件目录为:null.");
			return;
		}
		if(!yfile.exists()){
			System.out.println("源文件不存在.");
			return;
		}
		if(!mfile.exists()){
			mfile.mkdirs();
			System.out.println("目标目录不存在,已经创建");
		}
		File[] fileList=yfile.listFiles();
		if(fileList!=null){
			for(File f:fileList){
				if(f.isFile()&&f.getName().endsWith(".java")){
					String name=f.getName();
					String newname=name.replaceAll("\\.java$", ".mp3");
					Long time=System.currentTimeMillis();
					File mf=new File(mfile,time+newname);
					BufferedReader br=new BufferedReader(new FileReader(f));
					BufferedWriter bw=new BufferedWriter(new FileWriter(mf));
					String strs=null;
					while((strs=br.readLine())!=null){
						bw.write(strs);
						bw.newLine();
						bw.flush();
					}
					bw.close();
					br.close();
					count++;
				}
				if(f.isDirectory()){
					copyFile(f,mfile);
				}
			}
			
		}
	}
}

运行结果如下:


2.字节流
(1)字节输出流FileOutputStream
a、创建字节输出流对象
b、调用写数据的方式
c、释放资源
(2)字节输入流FileInputStream
a、创建字节输入流对象
b、调用读取数据的方式,并显示
c、释放资源
(3)示例:
package Test1;

import java.io.*;

public class FileTest {
	public static void main(String[] args) throws IOException {

		FileInputStream fis = new FileInputStream("a.txt");
		FileOutputStream fos =new FileOutputStream("G:\\CopyFile.txt");
		byte[] bys =new byte[1024];
		int len;
		while((len=fis.read(bys))!=-1){
			fos.write(bys,0,len);
			System.out.println(new String(bys,0,len));
		}
		fos.close();
		fis.close();
	}
}
运行结果:

(3)注意:
        二进制流数据:图片,视频,音频等...;由于二进制的合并为字符,在我们使用的编码表中没有对应的数据,那么,将来在写回去的时候,就会有数据的丢失,所以,二进制流数据只能使用字节流进行操作。

  (4)带缓冲区的输入出输出流

             ▪BufferedInputStream是带缓冲区的输入流,默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能;

             ▪BufferedOutputStream是带缓冲区的输出流,能够提高文件的写入效率。

            ▪ BufferedInputStream与BufferedOutputStream分别是FilterInputStream类和FilterOutputStream类的子类,实现了装饰设计模式。

  (5)小案例:

package Test1;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileTest {
	public static void main(String[] args) throws IOException {
		//高效字节流一次读写一个字节数组
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\酷狗下载\\信乐团 - 假如.mp3"));
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("love.mp3"));
			byte[] bys = new byte[1024];
			int len = 0;
			while((len=bis.read(bys))!=-1){
				bos.write(bys,0,len);
			}
			bos.close();
			bis.close();
			System.out.println("复制完成!");
	}
}
3.转换流

1:标准的输入输出流

a、public static final InputStream in :“标准”输入流。(System.in)--InputStream(字节输出流)

b、public static final PrintStream out:”标准“输出流 。(System.out)--PrintStream (字节输入流)

2.字节输入流转成字符输入流

a、方法:

字节流通向字符流的桥梁
InputStream ---->  InputStreamReader   -----> BufferedReader

b、小练习,想自己封装一个键盘录入数据,并存储到文本文件中:

import java.io.*;

public class FileTest {
	public static void main(String[] args) throws IOException {
		InputStream is = System.in;
		InputStreamReader isr = new InputStreamReader(is);
		BufferedReader br = new BufferedReader(isr);
		// 封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

		String line = null;
		while ((line = br.readLine()) != null) {
			// 只要是键盘录入,就的自己定义结束条件
			if ("over".equals(line)) {
				break;
			}
			bw.write(line);
			bw.newLine();
			bw.flush();
		}

		bw.close();
		br.close();
	}
}

理解:字符流读写数据的底层其实还是调用的字节流,只不过把字节流按照编码顺序排成了字符,从而读出来的是字符所以说既然底层调用的是字节流,那么字节流通过InputStreamReader就可以转成字符流,(其实就是把字节加入了一些编码顺序)所以说 万流之根源乃字节流,根源演变成了其他流,所以说 字节流可以转字符流,而反过来就不可以。

3.字节输出流转字符输出流:

a、方法:OutputStream  -- >  OutputStreamWriter   -->  BufferedWriter

b、小案例,需求:把文本文件的数据通过标准输出流的方式显示在控制台。

import java.io.*;

public class FileTest {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
		// 封装目的地
		OutputStream os = System.out;
		OutputStreamWriter osw = new OutputStreamWriter(os);
		BufferedWriter bw = new BufferedWriter(osw);

		// BufferedWriter bw = new BufferedWriter(new
		// OutStreamWriter(System.out));

		String line = null;
		while ((line = br.readLine()) != null) {
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		System.out.println();
		bw.close();
		br.close();
	}
}
理解:这句话 "OutputStreamWriter 是字符流通向字节流的桥梁" 难理解,因为不知道为什么字符流是字节流的桥梁,(按字节的流向,字符流读进来文字,按照字符流写入文件,底层还是调用字节流写入文件的,所以是字符流通向字节流的桥梁)不用管OutputStreamWriter是谁到谁的桥梁,我就说上面的是字节流转字符流还是字符流转字节流?肯定是字节流转字符流,反过来就不可以(万流之根源乃字节流,根源演变成了其他流)

4:编码问题

流的编码问题:字符流=字节流+编码表
如果你想在IO流中使用指定编码下数据,用转换流。
编码问题其实很简单,永远使用同一种编码即可。
FileReader: FileInputStream+GBK

FileWriter:FileOutputStream+GBK

//写入的时候用的字符流的UTF-8编码

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8"); // 指定编码UTF-8

osw.write("中国");

osw.close();

//那么读出的时候如果用字符流 也应该用 UTF-8编码

InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "UTF-8");

char[] chs = new char[1024];

int len = isr.read(chs);

String str = new String(chs, 0, len);

System.out.println(str);

如下面代码:

import java.io.*;

public class FileTest {
	public static void main(String[] args) throws IOException {
		// OutputStreamWriter(OutputStream out, String charsetName)
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8");// 指定编码UTF-8
		osw.write("中国你好!");
		osw.close();
		InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "UTF-8");
		char[] chs = new char[1024];
		int len = isr.read(chs);
		String str = new String(chs, 0, len);
		System.out.println(str);
	}
}
5.打印流

a、PrintStream:字节打印流

b、PrintWriter:字符打印流

1、打印流特点:

a、可以写入任意类型的数据。

b、可以自动刷新。必须先启动,并且是使用println,printf及format方法才有效。

c、可以直接对文件进行写入。

d、注意:打印流只有写数据的,没有读取数据的。

2、构造方法:

a、PrintWriter(String fileName) :使用指定文件创建不具有自动行刷新的新 PrintWriter

bPrintWriter(OutputStream out):根据现有的OutputStream创建不带自动行刷新的新 PrintWriter

c、PrintWriter(OutputStream out,boolean autoFlush):通过现有的OutputStream创建新的PrintWriter。

d、PrintWriter(Writer out):创建不带自动行刷新的新PrintWriter。

ePrintWriter(Writerout,boolean autoFlush):创建新PrintWriter

3.PrintWriter的 print() 可以写任意类型数据:

PrintWriter 自动刷新功能(必须开启了自动刷新 然后还得是调用println,printf及format方法,才能自动刷新)。

PrintWriter pw = new PrintWriter(new FileWriter("d.txt"), true);PrintWriter的println()能够自动换行。

4.案例:用打印流复制文本文件

public class FileTest {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("PrintWriterDemo.java"));
		// 封装目的地
		PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);
		String line = null;
		while ((line = br.readLine()) != null) {
			pw.println(line);
		}
		pw.close();
		br.close();
	}
}
5.注意:
a、读取文件的时候,如果是文件夹,会出现:FileNotFoundException: test (拒绝访问。)

b、写文件的时候,如果没有后缀名,它也会自动生成一个文件,而这个种类型的文件通过记事本类型的软件是可以打开的。
6.序列化流

(1)序列化:把对象按照流一样的方式传输或者存储。

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。

void writeObject(Object obj)

(2)反序列化:把网络中的流数据或者文件中的流数据还原成对象。

ObjectInputStream:ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化

Object readObject()

(3)注意问题:

a、如果类的对象想被序列化流操作,请实现序列化接口。

b、看到了类实现了Serializable接口,如果想解决黄色警告线,请点击鼠标。

c、java.io.NotSerializableException 没有实现序列化接口异常

d、类通过实现 java.io.Serializable 接口以启用其序列化功能。该接口被称为序列化接口,是一个标记接口。

没有任何功能需要实现。类一旦实现了该接口,那么,该类的对象就可以被序列化流进行操作。

(4)为什么要写一个序列号?

对象在被序列化流进行操作的时候,会记录一个序列号值。而这个序列号值跟对象的成员相关。

最开始的时候:

Person类的对象 p的id是100

write写到文件中:id -- 100

read读取数据: id -- 100

后来,我们把write方法给注释了,然后修改了Person类,这个类被修改后,成员就发生了改变。

那么,id也就相应的发生改变

Person类的对象id改为了200

那么,直接读取,文件中的id是100,而我们有的id是200,他们不匹配,所以报错了。

那么,在很多情况下,我们的类中的成员可能会发生改变,不可能说每次改变,我都需要把数据重写入一次。

怎么解决这种情况呢?

先写,在读取。没有问题。

先写,后修改了类,在读取,有问题。

很简单,我们想了这样的一个问题:他们之所以出错,就是因为那个id值不匹配,如果我们直接在类中给一个固定的id值。

那么,无论你怎么修改类的成员,这个id值是不变化的,那这样的话,以后的id永远都是一样的。就不会再因为简单的修改出问题。

问题呢?怎么定义这个id值呢?

private static final long serialVersionUID = 333558257579870816L;

(5)

示例:

[java]  view plain copy
  1. /* 
  2. SequenceInputStream 
  3. 合并流 
  4. 需求:将三个文本文件中的数据合并到一个文本文件中 
  5. 思路:1、创建一个Vector集合,将三个文本文件字节流添加到集合中 
  6.       2、创建Enumeration对象,创建SequnceInputStream对象关联Enumeration 
  7.       3、输出流关联新文本文件 
  8.       4、反复读写操作 
  9. */  
  10. import java.util.*;  
  11. import java.io.*;  
  12.   
  13. class  SequenceInputStreamDemo  
  14. {  
  15.     public static void main(String[] args)throws IOException  
  16.     {  
  17.         Vector<InputStream> ve=new Vector<InputStream>();//创建vector集合,并添加相关流对象  
  18.         ve.add(new FileInputStream("1.txt"));  
  19.         ve.add(new FileInputStream("2.txt"));  
  20.         ve.add(new FileInputStream("3.txt"));  
  21.   
  22.         Enumeration<InputStream> en=ve.elements();//创建枚举对象  
  23.         SequenceInputStream sis=new SequenceInputStream(en);//合并流  
  24.   
  25.         FileOutputStream fos=new FileOutputStream("4.txt");//关联写入文件  
  26.           
  27.         //反复读写操作  
  28.         byte[] buf=new byte[1024];  
  29.         int len=0;  
  30.         while((len=sis.read(buf))!=-1)  
  31.         {  
  32.             fos.write(buf,0,len);  
  33.         }  
  34.           
  35.         //关流  
  36.         fos.close();  
  37.         sis.close();  
  38.     }  
  39. }  

练习:

[java]  view plain copy
  1. /* 
  2. 切割文件 
  3. 需求:将一个mp3文件按1M大小切割成几部分 
  4. 思路:1、使用文件字节流关联mp3文件 
  5.       2、定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中 
  6.  
  7. */  
  8. import java.util.*;  
  9. import java.io.*;  
  10.   
  11. class  SplitFile  
  12. {  
  13.     public static void main(String[] args) throws IOException  
  14.     {  
  15.         //指定要切割的文件  
  16.         File file=new File("C:\\Users\\asus\\Desktop\\苏芮 - 一样的月光.mp3");  
  17.         //将指定文件进行切割  
  18.         splitFile(file);  
  19.   
  20.         //指定要合并到的文件  
  21.         File file1=new File("E:\\Java Study\\Practice\\day20\\splitFile\\一样的月光.mp3");  
  22.         //将部分文件进行合并指定文件中  
  23.         merge(file1);  
  24.   
  25.     }  
  26.     //接收一个文件,将其按1M大小进行切割  
  27.     public static void splitFile(File file)throws IOException  
  28.     {  
  29.         //关联要切割的文件  
  30.         BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));  
  31.           
  32.         BufferedOutputStream bos=null;  
  33.   
  34.         //定义1M大小存储容器  
  35.         byte[] buf=new byte[1024*1024];  
  36.         int len=0,x=0;  
  37.         while ((len=bis.read(buf))!=-1)  
  38.         {  
  39.             //每满1M就写入一个新文件中  
  40.             bos=new BufferedOutputStream(new FileOutputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+(++x)+".part"));  
  41.             bos.write(buf,0,len);  
  42.             bos.close();//没写完一个文件要记得关流  
  43.         }  
  44.         //关流  
  45.         bis.close();  
  46.     }  
  47.   
  48.     //将部分文件合并为一个可执行文件  
  49.     public static void merge(File file)throws IOException  
  50.     {  
  51.         //定义一个集合存储这些部分文件关联路径数据  
  52.         ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();  
  53.   
  54.         for (int x=1;x<=6 ; x++)  
  55.         {  
  56.             al.add(new FileInputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+x+".part"));  
  57.         }  
  58.           
  59.         //因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类  
  60.         final  ListIterator<FileInputStream> it=al.listIterator();  
  61.         Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()  
  62.         {  
  63.             public boolean hasMoreElements()  
  64.             {  
  65.                 return it.hasNext();  
  66.             }  
  67.   
  68.             public FileInputStream nextElement()  
  69.             {  
  70.                 return it.next();  
  71.             }  
  72.         };  
  73.   
  74.         //关联枚举对象  
  75.         SequenceInputStream sis=new SequenceInputStream(en);  
  76.   
  77.         //将合并的文件数据写入指定文件中  
  78.         FileOutputStream fos=new FileOutputStream(file);  
  79.           
  80.         //定义临时存储数据的数组  
  81.         byte[] buf=new byte[1024];  
  82.         int len=0;  
  83.         while((len=sis.read(buf))!=-1)  
  84.         {  
  85.             fos.write(buf,0,len);//写数据  
  86.         }  
  87.   
  88.         //关流  
  89.         fos.close();  
  90.         sis.close();  
  91.   
  92.     }  
  93.   
  94. }  




















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值