java复习第十六天 递归应用

递归解决的问题


猴子偷桃问题

/*
 * 	小猴子第一天摘下若干桃子,当即吃掉一半,又多吃一个.第二天早上又将剩下的桃子吃一半,又多吃一个.
	以后每天早上吃前一天剩下的一半另一个.到第10天早上猴子想再吃时发现,只剩下一个桃子了.问第一天猴子共摘多少个桃子?
	
	出口:当天数是10的时候,返回1;当天数大于10或者小于1就直接返回0
	规律:当天的桃子数=(后一天的桃子数+1)*2
 */
public class DiGuiTest {
	public static void main(String[] args) {
		System.out.println(getNumber(1));// 1534
	}

	/**
	 * 求对应天数的桃子个数
	 * 
	 * @param day
	 * @return
	 */
	public static int getNumber(int day) {
		// 出口:当天数是10的时候,返回1;当天数大于10或者小于1就直接返回0
		if (day == 10) {
			return 1;
		} else if (day > 10 || day < 1) {
			return 0;
		} else {
			// 规律:当天的桃子数=(后一天的桃子数+1)*2
			return (getNumber(day + 1) + 1) * 2;
		}
	}
}

递归遍历文件夹中指定类型的文件

import java.io.File;

/*
 * 递归遍历目录下指定后缀名结尾的文件名称:
 * 	1.将目标目录封装成File对象
 * 	2.调用查找指定后缀名结尾的文件的方法,将目标目录文件对象传递给这个方法
 * 	3.在方法内部进行判断当前文件是不是一个标准文件
 * 		如果是标准文件且后缀名是以.jpg结尾的,那么直接输出该文件的全路径名
 * 	4.如果是一个文件夹,那么就获取该文件夹底下所有的子文件,然后遍历每一个子文件,将每一个子文件作为参数再次调用该方法
 * 
 * 出口:当前文件是一个标准文件
 * 规律:当前文件是一个文件夹,就遍历当前文件夹的子文件再次调用该方法
 */
public class DiGuiTest2 {
	public static void main(String[] args) {
		// 1.将目标目录封装成File对象
		File file = new File("E:/Test");
		// 2.调用查找指定后缀名结尾的文件的方法,将目标目录文件对象传递给这个方法
		searchFile(file);
	}

	/**
	 * 查找指定后缀名结尾的文件
	 * 
	 * @param file
	 */
	private static void searchFile(File file) {
		// 3.在方法内部进行判断当前文件是不是一个标准文件
		if (file.isFile() && file.getAbsolutePath().endsWith(".jpg")) {//出口:当前文件是一个标准文件
			// 如果是标准文件且后缀名是以.jpg结尾的,那么直接输出该文件的全路径名
			System.out.println(file.getAbsolutePath());
		}else if(file.isDirectory()){//规律:当前文件是一个文件夹,就遍历当前文件夹的子文件再次调用该方法
			//4.如果是一个文件夹,那么就获取该文件夹底下所有的子文件,然后遍历每一个子文件,将每一个子文件作为参数再次调用该方法
			File[] files = file.listFiles();
			for (File f : files) {
				searchFile(f);
			}
		}
	}

}

递归删除文件夹

import java.io.File;

/*
 * 递归删除一个带内容的文件夹:
 * 	1.将目标目录封装成File对象
 * 	2.直接调用删除文件夹的方法
 * 	3.在方法内部判断当前文件是否是一个标准文件
 * 		如果是,直接删除
 * 	4.如果是文件夹,获取该文件夹底下所有的子文件,将子文件当做参数再次调用该方法
 * 
 * 出口:是文件就删除
 * 规律:是文件夹就遍历所有的子文件再次调用删除方法
 */
public class DiGuiTest3 {
	public static void main(String[] args) {
		// 1.将目标目录封装成File对象
		File file = new File("D:/Test");
		// 2.直接调用删除文件夹的方法
		deleteFolder(file);
	}

	/**
	 * 删除文件夹
	 * 
	 * @param file
	 */
	private static void deleteFolder(File file) {
		//3.在方法内部判断当前文件是否是一个标准文件
		if(file.isFile()){//出口:是文件就删除
			//如果是,直接删除
			file.delete();
		}else{//规律:是文件夹就遍历所有的子文件再次调用删除方法
			File[] files = file.listFiles();
			for (File f : files) {
				deleteFolder(f);//将该文件夹底下所有的子文件都删除
			}
			//再删除本身的文件夹
			file.delete();
		}
	}
}

BufferedReader

import java.io.BufferedReader;
import java.io.FileReader;

/*
 * BufferedReader:是对普通字符读取流进行了增强,提高了读取字符数据的能力
 * 特殊的方法:readLine()直接读取一行字符串
 */
public class BufferedReaderDemo {
	public static void main(String[] args) {
		try (BufferedReader br = new BufferedReader(new FileReader("E:/修仙.txt"));) {
			/*
			 * public String readLine()读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
			 * 	返回值:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null 
			 */
			String line;//保存每次读取的内容
			while((line=br.readLine())!=null){
				System.out.println(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}import java.io.BufferedReader;
import java.io.FileReader;

/*
 * BufferedReader:是对普通字符读取流进行了增强,提高了读取字符数据的能力
 * 特殊的方法:readLine()直接读取一行字符串
 */
public class BufferedReaderDemo {
	public static void main(String[] args) {
		try (BufferedReader br = new BufferedReader(new FileReader("E:/修仙.txt"));) {
			/*
			 * public String readLine()读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
			 * 	返回值:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null 
			 */
			String line;//保存每次读取的内容
			while((line=br.readLine())!=null){
				System.out.println(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

BufferWriter

import java.io.BufferedWriter;
import java.io.FileWriter;

/*
 * BufferedWriter:是对普通字符输出流的增强,提高了写出字符数据的速度
 * 特殊的方法:newLine()写出一个换行分隔符
 */
public class BufferedWriterDemo {
	public static void main(String[] args) {
		try (BufferedWriter bw = new BufferedWriter(new FileWriter("D:/test.txt"));) {
			bw.write("哈哈");
			bw.newLine();
			bw.write("哈哈");
			bw.newLine();
			bw.write("哈哈");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
 
 

FileWriter

FileReader

import java.io.FileReader;
import java.io.FileWriter;

/*
 * FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。
 * 		要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
 * FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。
 * 		要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
 */
public class CopyTextFileTest {
	public static void main(String[] args) {
		// 把E:/a.txt内容复制到D:/copy.txt中

		String srcPath = "E:/a.txt";
		String destPath = "D:/copy.txt";

		copyTextFile(srcPath, destPath);
	}

	/**
	 * 使用普通字符流拷贝文本文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	private static void copyTextFile(String srcPath, String destPath) {
		try (// 先读
				FileReader fr = new FileReader(srcPath);
				// 后写
				FileWriter fw = new FileWriter(destPath);) {
			char[] cbuf = new char[1024];// 自定义;
			int len;// 记录每次读取的字符个数
			// 循环读写
			while ((len = fr.read(cbuf)) != -1) {
				// 读多少就写出多少
				fw.write(cbuf, 0, len);
			}
			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
复制方式2
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;

public class CopyTextFileTest2 {
	public static void main(String[] args) {
		// 把E:/a.txt内容复制到D:/copy.txt中

		String srcPath = "E:/修仙.txt";
		String destPath = "D:/copy.txt";
		long start = System.currentTimeMillis();// 开始时间
		copyTextFile(srcPath, destPath);
		long end = System.currentTimeMillis();
		System.out.println(end - start);
		/*
		 * 普通字节流:1268
		 * 字节缓冲流:239
		 * 普通字符流:755
		 * 字符缓冲流:744
		 * 使用了readLine的字符缓冲流:896
		 */
	}

	/**
	 * 使用字符缓冲拷贝文本文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	private static void copyTextFile2(String srcPath, String destPath) {
		try (// 先读
				BufferedReader br = new BufferedReader(new FileReader(srcPath));
				// 后写
				BufferedWriter bw = new BufferedWriter(new FileWriter(destPath));) {
			char[] buf = new char[1024];// 自定义容器
			int len;// 记录实际读取的字符个数
			// 循环读写
			while ((len = br.read(buf)) != -1) {
				// 读多少就写出多少
				bw.write(buf, 0, len);
			}
			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用字符缓冲流的readLine和newLine拷贝文件的方法(拷贝的目标文件总是会多出一个空行)
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	private static void copyTextFile(String srcPath, String destPath) {
		try (// 先读
				BufferedReader br = new BufferedReader(new FileReader(srcPath));
				// 后写
				BufferedWriter bw = new BufferedWriter(new FileWriter(destPath));) {

			String line;// 保存每次读取的内容
			// 循环读写
			while ((line = br.readLine()) != null) {
				// 将数据写出去
				bw.write(line);
				// 换行
				bw.newLine();
			}
			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

InputStream

mport java.io.FileInputStream;
import java.io.InputStreamReader;

/*
 * InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
 * 	它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
 * 需求:将D:/test.txt中的文本读取出来
 * 
 * 注意!!!:编码和解码的编码表要保持一致
 */
public class InputStreamReaderDemo {
	public static void main(String[] args) {
		try(//public InputStreamReader(InputStream in)创建一个使用默认字符集的 InputStreamReader。
			//InputStreamReader isr = new InputStreamReader(new FileInputStream("D:/test.txt"));
			//public InputStreamReader(InputStream in,String charsetName)创建使用指定字符集的 InputStreamReader
			InputStreamReader isr = new InputStreamReader(new FileInputStream("D:/test.txt"),"GBK");) {
			// public int read()读取一个字符
			//char ch = (char) isr.read();
			//System.out.println(ch);
			
			// public int read(char[] cbuf)最多读取cbuf.length个字符;如果没有字符了就返回-1
			char[] cbuf = new char[1024];//自定义容器
			int len = isr.read(cbuf);//实际读取的字符个数
			String s = new String(cbuf,0,len);//将读取到的字符转换成字符串
			System.out.println(s);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

OutputStream

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

/*
 * 字符流都有缓冲区
 * 
 * OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
 * 	它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
 * 
 * 需求:将"今天好闷热"写出到D:/test.txt中
 */
public class OutputStreamWriterDemo {
	public static void main(String[] args) {
		try(//public OutputStreamWriter(OutputStream out)创建使用默认字符编码的 OutputStreamWriter
			//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:/test.txt"));
			//public OutputStreamWriter(OutputStream out,String charsetName)创建使用指定字符集的 OutputStreamWriter
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:/test.txt"),"GBK");
				) {
			
			// public void write(int c)一次写出一个字符
			//osw.write('今');
			
			//char[] cbuf = {'今','天','好','闷','热'};
			// public void write(char[] cbuf)写出一个字符数组
			//osw.write(cbuf);
			
			// public void write(char[] cbuf,int off,int len)写出字符数组中的一部分
			//osw.write(cbuf, 0, 2);
			
			// public void write(String str)写出一个字符串
			osw.write("今天好闷热");
			
			// public void write(String str,int off,int len)写出字符串中的一部分
			//osw.write("今天好闷热", 2, 3);
		} catch (Exception e) {
			e.printStackTrace();
		}
		

	}
}

工具类积累,开发可以直接用

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class IOUtils {
	/**
	 * 使用字符缓冲流拷贝文本文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	public static void copyTextFile2(String srcPath, String destPath) {
		try (// 先读
			BufferedReader br = new BufferedReader(new FileReader(srcPath));
			// 后写
			BufferedWriter bw = new BufferedWriter(new FileWriter(destPath));) {
			char[] buf = new char[1024];// 自定义容器
			int len;// 记录实际读取的字符个数
			// 循环读写
			while ((len = br.read(buf)) != -1) {
				// 读多少就写出多少
				bw.write(buf, 0, len);
			}
			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用普通字符流拷贝文本文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	public static void copyTextFile(String srcPath, String destPath) {
		try (// 先读
				FileReader fr = new FileReader(srcPath);
				// 后写
				FileWriter fw = new FileWriter(destPath);) {
			char[] cbuf = new char[1024];// 自定义;
			int len;// 记录每次读取的字符个数
			// 循环读写
			while ((len = fr.read(cbuf)) != -1) {
				// 读多少就写出多少
				fw.write(cbuf, 0, len);
			}
			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用字节缓冲流拷贝标准文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	public static void copyFile2(String srcPath, String destPath) {
		try (// 先读
				// public BufferedInputStream(InputStream in)创建字节缓冲读取流对象
				BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));
				// 后写
				// public BufferedOutputStream(OutputStream out)创建字节缓冲输出流对象
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath));) {

			byte[] buf = new byte[1024];// 自定义容器
			int len;// 保存每次实际读取的字节个数
			// 循环读写,如果返回值不等于-1就说明还有数据
			while ((len = bis.read(buf)) != -1) {
				// 读多少就写出多少
				bos.write(buf, 0, len);
			}
			// bos.flush();//将缓冲区中的字节刷新到硬盘上

			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用普通字节流拷贝标准文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	public static void copyFile(String srcPath, String destPath) {
		try ( // 先读
				FileInputStream fis = new FileInputStream(srcPath);
				// 后写
				FileOutputStream fos = new FileOutputStream(destPath);) {
			byte[] buf = new byte[1024];// 定义一个容器用于存放读取的字节
			int len;// 记录每次实际读取的字节个数
			// 循环读写,只要读取的长度不等于-1就表明还有数据可以读取
			while ((len = fis.read(buf)) != -1) {
				// 读了多少个字节就写出多少个字节
				fos.write(buf, 0, len);
			}
			System.out.println("文件拷贝成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 关闭所有的字节读取流
	 * 
	 * @param fis
	 *            字节读取流的子类对象
	 */
	public static void closeIn(InputStream fis) {
		// 如果fis没有被赋值,那么默认值就是null,如果直接调用close方法就会空指针
		// 所以需要判断fis不等于null才去调用close方法
		if (null != fis) {
			try {
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 关闭所有的字节输出流
	 * 
	 * @param fos
	 *            字节输出流子类对象
	 */
	public static void closeOut(OutputStream fos) {
		// 如果fos没有被初始化,那么默认值就是null,如果拿null去调用方法,肯定会空指针
		// 判断fos不等于null的时候,再去调用close方法
		if (null != fos) {
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

输出流

(1)

import java.io.FileOutputStream;

/*
 * 需求:向D:/test.txt中输出"Hello,美女"
 * 分析实现:一看输出的是文本,使用字符流更合适,但是字符流是由字节流包装得来的,所以需要先学习字节流
 * 写出数据的几个小问题?
 * 	1.如何实现数据的追加写入?
 * 		可以使用两个参数的构造方法,将第二个参数置为true
 * 	2.如何实现数据的换行分割呢?
 * 		可以在数据的后面加\r\n
 * 	3.创建文件输出流做了哪些事情?
 * 		向指定文件搭建了一个通道,通过这个通道写出数据
 * 	4.为什么流用完之后需要关闭?
 * 		为了节省资源,如果大家都不关闭,就会造成内存泄漏,内存泄漏多了程序就会crash掉
 */
public class FileOutputStreamDemo {

	public static void main(String[] args) {
		try {
			//构造方法
			//public FileOutputStream(String name)创建一个向具有指定名称的文件中写入数据的输出文件流
			FileOutputStream fos = new FileOutputStream("D:/test.txt");
			//public FileOutputStream(String name,boolean append)创建一个向具有指定 name 的文件中写入数据的输出文件流
			//FileOutputStream fos = new FileOutputStream("D:/test.txt", true);
			
			//写出数据的方法
			byte[] bytes = "Hello,美女\r\n".getBytes();
			System.out.println(bytes.length);//16
			//public void write(byte[] b)将 b.length 个字节从指定 byte 数组写入此文件输出流中
			//fos.write(bytes);
			//public void write(byte[] b,int off,int len)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流
			//fos.write(bytes, 0, 5);
			//public void write(int b)将指定字节写入此文件输出流
			fos.write('a');
			fos.write(97);
			fos.write("97".getBytes());
			
			//关闭流的方法
			//public void close()关闭此文件输出流并释放与此流有关的所有系统资源
			fos.close();
			System.out.println("写出数据成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

(2)
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/*
 * 需求:向D:/test.txt中输出"你们都很帅",完事之后确保流关闭
 * 分析:首先使用FileOutputStream输出,然后使用try...catch进行捕获
 */
public class FileOutputStreamDemo2 {
	public static void main(String[] args) {
		// 传统关流方式
		// method1();

		// 新特性关流方式
		method2();
	}

	/*
	 * 新特性关流方式:JDK1.7新特性 try(只能存放的是需要关闭的资源){ ... }catch(...){ ... }finally{ ...
	 * }
	 */
	private static void method2() {
		// 1.创建文件输出流对象
		try (FileOutputStream fos = new FileOutputStream("D:/test.txt");) {// 3.新特性关流:当try代码执行完或者发生异常时会关流
			// 2.使用write方法将字节数组写出到指定文件中
			fos.write("你们都很帅".getBytes());
			System.out.println("写出数据成功");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("啦啦啦~");
		}
	}

	// 传统关流方式
	private static void method1() {
		// 1.创建文件输出流对象
		FileOutputStream fos = null;
		try {
			int a = 1 / 0;// 如果代码在这里出现了问题,那么fos就没有被初始化
			fos = new FileOutputStream("D:/test.txt");
			// 2.使用write方法将字节数组写出到指定文件中
			fos.write("你们都很帅".getBytes());
			int i = 1 / 0;// 如果在这里出现了异常,那么关闭流的代码就执行不到,那么就会内存泄漏
			System.out.println("写出数据成功");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 3.关闭流
			closeOut(fos);
		}
	}

	/**
	 * 关闭所有的字节输出流
	 * 
	 * @param fos
	 *            字节输出流子类对象
	 */
	private static void closeOut(OutputStream fos) {
		// 如果fos没有被初始化,那么默认值就是null,如果拿null去调用方法,肯定会空指针
		// 判断fos不等于null的时候,再去调用close方法
		if (null != fos) {
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

(1)
import java.io.FileInputStream;

/*
 * 需求:从D:/test.txt中读取数据打印在控制台
 * 分析:发现使用字符流比较合适,但是字符流是由字节流包装得来的,所以需要先学习字节流
 */
public class FileInputStreamDemo {
	public static void main(String[] args) {
		try {
			//构造方法
			//public FileInputStream(String name)通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定
			FileInputStream fis = new FileInputStream("D:/test.txt");
			
			//读取数据
			/*
			 * public int read(byte[] b)
			 * 	从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
			 * 	返回值是读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1
			 */
			//自定义一个容器
			byte[] b = new byte[1024];
			//int len = fis.read(b);//len是实际读取的字节长度
			//System.out.println(len);//15
			//public int read(byte[] b,int off,int len)从此输入流中将最多 len 个字节的数据读入一个 byte 数组中
			//int len = fis.read(b, 0, 6);
			//System.out.println(len);//6
			//将实际读取到的字节转换成字符串
			//String result = new String(b, 0, len);
			//System.out.println(result);+
			//public int read()从此输入流中读取一个数据字节
			int i = fis.read();
			System.out.println((char)i);//a
			
			//关闭资源
			//public void close()关闭此文件输入流并释放与此流有关的所有系统资源
			fis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


(2)

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/*
 * 需求:从D:/test.txt中读取数据打印在控制台
 * 分析:发现使用字符流比较合适,但是字符流是由字节流包装得来的,所以需要先学习字节流
 */
public class FileInputStreamDemo2 {
	public static void main(String[] args) {
		// 传统关流方式
		// method1();

		// 新特性关流方式
		method2();

	}

	/*
	 * 新特性关流方式:JDK1.7新特性
	 * 	try(只能存放需要关闭资源的代码){
	 * 		...
	 * 	}catch(...){
	 * 		...
	 * 	}finally{
	 * 		...
	 * 	}
	 */
	private static void method2() {
		// 1.创建文件读取流
		try(FileInputStream fis = new FileInputStream("D:/test.txt");) {// 3.新特性关流:当try代码执行完或者发生异常时会关流
			// 2.读取数据
			byte[] buf = new byte[1024];// 定义一个容器
			int len = fis.read(buf);// 实际读取的长度
			String result = new String(buf, 0, len);// 将读取的字节转换成字符串
			System.out.println(result);// a你们都很帅
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("啦啦啦~");
		}
	}

	// 传统关流方式
	private static void method1() {
		// 1.创建文件读取流
		FileInputStream fis = null;
		try {
			// int i = 1 / 0;// 如果代码在这里发生了异常,那么fis就无法赋值
			fis = new FileInputStream("D:/test.txt");
			// 2.读取数据
			byte[] buf = new byte[1024];// 定义一个容器
			int len = fis.read(buf);// 实际读取的长度
			String result = new String(buf, 0, len);// 将读取的字节转换成字符串
			System.out.println(result);// a你们都很帅
			// i = 1 / 0;// 如果在这里发生了异常,那么关闭流的代码就执行不到
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 3.关闭资源
			closeIn(fis);
		}
	}

	/**
	 * 关闭所有的字节读取流
	 * 
	 * @param fis
	 *            字节读取流的子类对象
	 */
	private static void closeIn(InputStream fis) {
		// 如果fis没有被赋值,那么默认值就是null,如果直接调用close方法就会空指针
		// 所以需要判断fis不等于null才去调用close方法
		if (null != fis) {
			try {
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

复制文件

(1)

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

/* BufferedOutputStream:会对输出流进行增强,提高写出的速度
 * BufferedInputStream:会对读取流进行增强,提高读取的速度
 * 
 * 缓冲区里面的数据何时刷新到硬盘文件上呢?
	1.主动调用flush方法,强制将缓冲区中的所有数据刷新到硬盘文件里面去
	2.当调用输出流的close方法时,流在关闭之前会先调用flush方法
	3.当缓冲区溢出了,溢出的数据会刷新到硬盘文件里面去
	何时调用flush方法比较合适?
    	当有一部分数据需要立马刷新出去的时候,可以调用flush
    	数据早刷新和晚刷新出去无所谓的时候,在关流的时候会主动的调用flush方法
 */
public class CopyFileTest2 {
	public static void main(String[] args) {
		// 把E:/老鼠爱大米.mp3复制到当前项D:/copy.mp3中
		String srcPath = "E:/老鼠爱大米.mp3";
		String destPath = "D:/copy.mp3";
		
		long start = System.currentTimeMillis();//开始时间
		IOUtils.copyFile2(srcPath, destPath);
		long end = System.currentTimeMillis();//结束时间
		System.out.println(end-start);//普通字节流:49	字节缓冲流:14
	}

	/**
	 * 使用字节缓冲流拷贝标准文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	private static void copyFile(String srcPath, String destPath) {
		try (// 先读
				// public BufferedInputStream(InputStream in)创建字节缓冲读取流对象
				BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));
				// 后写
				// public BufferedOutputStream(OutputStream out)创建字节缓冲输出流对象
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath));) {

			byte[] buf = new byte[1024];// 自定义容器
			int len;// 保存每次实际读取的字节个数
			// 循环读写,如果返回值不等于-1就说明还有数据
			while ((len = bis.read(buf)) != -1) {
				// 读多少就写出多少
				bos.write(buf, 0, len);
			}
			// bos.flush();//将缓冲区中的字节刷新到硬盘上

			System.out.println("拷贝文件成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

(2)复制文件
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class CopyFileTest {
	public static void main(String[] args) {
		// 把E:/a.txt内容复制到D:/copy.txt中
		copyFile("E:/a.txt", "D:/copy.txt");
		//把E:/悟空.jpg内容复制到D:/copy.jpg中
		copyFile("E:/悟空.jpg", "D:/copy.jpg");
		//把E:/老鼠爱大米.mp3复制到当D:/copy.mp3中
		copyFile("E:/老鼠爱大米.mp3", "D:/copy.mp3");

	}

	/**
	 * 使用普通字节流拷贝标准文件
	 * 
	 * @param srcPath
	 *            原文件路径
	 * @param destPath
	 *            目标文件路径
	 */
	private static void copyFile(String srcPath, String destPath) {
		try ( // 先读
				FileInputStream fis = new FileInputStream(srcPath);
				// 后写
				FileOutputStream fos = new FileOutputStream(destPath);) {
			byte[] buf = new byte[1024];// 定义一个容器用于存放读取的字节
			int len;// 记录每次实际读取的字节个数
			// 循环读写,只要读取的长度不等于-1就表明还有数据可以读取
			while ((len = fis.read(buf)) != -1) {
				// 读了多少个字节就写出多少个字节
				fos.write(buf, 0, len);
			}
			System.out.println("文件拷贝成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void method() {
		// 先读
		FileInputStream fis = null;
		// 后写
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream("E:/a.txt");
			fos = new FileOutputStream("D:/copy.txt");
			byte[] buf = new byte[1024];// 定义一个容器用于存放读取的字节
			int len;// 记录每次实际读取的字节个数
			// 循环读写,只要读取的长度不等于-1就表明还有数据可以读取
			while ((len = fis.read(buf)) != -1) {
				// 读了多少个字节就写出多少个字节
				fos.write(buf, 0, len);
			}
			System.out.println("文件拷贝成功");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 先创建的流后关闭
			IOUtils.closeOut(fos);
			IOUtils.closeIn(fis);
		}
	}
}



猜你喜欢

转载自blog.csdn.net/a331685690/article/details/80021145