目录
递归
定义
方法定义中调用方法本身的现象
- 注意
(1) Math.max(Math.max(a,b),c); //方法的嵌套调用,这不是递归
(2) 递归一定要有出口,否则就是死递归
(3) 递归的次数不能太多,否则就内存溢出
(4) 构造方法不能递归使用
举例
阶乘
public static int jieCheng(int n) {
if(n==1) {
return 1;
}else {
return n*jieCheng(n-1);
}
}
斐波那契数列
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}
获取某个目录下所有.java结尾的文件路径
private static void getAllJavaFilePaths(File srcFolder) {
File[] fileArray = srcFolder.listFiles();
for (File file : fileArray) {
if (file.isDirectory()) {
getAllJavaFilePaths(file);
} else {
if (file.getName().endsWith(".java")) {
System.out.println(file.getAbsolutePath());
}
}
}
}
删除某文件夹包括内部所有文件或文件夹
private static void deleteFolder(File srcFolder) {
File[] fileArray = srcFolder.listFiles();
for(File file:fileArray) {
if(file.isDirectory()) {
deleteFolder(file);
}else {
System.out.println(file.getName()+"---"+file.delete());
}
}
System.out.println(srcFolder.getName()+"---"+srcFolder.delete())
}
IO流
IO流的分类
-
定义: IO用于在设备间进行数据传输的操作
-
分类
- 流向:
- 输入流: 读取数据
- 输出流: 写出数据
- 数据类型:
- 字节流:
- 字节输入流: 读取数据
- 字节输出流: 写出数据
- 字符流:
- 字符输入流: 读取数据
- 字符输出流: 写出数据
- 字节流:
- 流向:
-
注意:
(1) 一般我们在探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况下是按照数据类型来分的。
(2) 如果你操作的数据是文本数据,就用字符流。把你要操作的文件用windows自带的记事本打开,如果打开后数据你是可以读懂的,就可以使用字符流,如果不能读懂,就用字节流。
如果你什么都不知道,就用字节流。
字节输出流操作
操作步骤
A: 创建字节输出流对象
B: 写数据
C: 释放资源
举例
FileOutputStream fos = new FileOutputStream("fos.txt");
/*
* 创建字节输出流对象做了几件事情
* A:调用系统功能去创建文件
* B:创建fos对象
* C:把fos对象指向这个文件
*/
// 写数据
fos.write("hello.IO".getBytes());
fos.write("java".getBytes());
// 释放资源
fos.close();
/*
* 为什么一定要close()呢?
* A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
* B:通知系统去释放跟该文件相关的资源
*/
FileOutputStream方法
- 方法
public void write(int b) // 写一个字节
public void write(byte[] byte) // 写一个字节数组
public void write(byte[] b,int off,int len) // 写一个字节数组的一部分
- 举例
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos2.txt");
// 调用write()方法
fos.write(97);
fos.write(57);// 字符9
fos.write(55);// 字符7
// public void write(byte[] b)
byte[] bys = {97,98,99,100,101};
fos.write(bys);
// public void write(byte[] b,int off,int len)
fos.write(bys, 1, 3);
// 结果:a97abcdebcd
- 如何实现数据的换行?
Windows: \r\n
Linux: \n
Mac: \r - 如何实现数据的追加写入?
用构造方法带第二个参数是true的情况即可
加入异常处理的字节输出流操作举例
// 分开做异常处理
// FileOutputStream fos = null;
// try {
// fos = new FileOutputStream("fos4.txt");
// } catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// try {
// fos.write("java".getBytes());
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// try {
// fos.close();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// 一起做异常处理
// try {
// FileOutputStream fos = new FileOutputStream("fos4.txt");
// fos.write("java".getBytes());
// fos.close();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// 改进版
// 为了在finally里面能够看到该对象,就必须定义到外面,为了
// 访问不出问题,还必须给初始化值
FileOutputStream fos = null;
try {
fos = new FileOutputStream("fos4.txt");
fos.write("java".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 为了保证close()一定会执行,就放到这里了
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
字节输入流操作
操作步骤
A: 创建字节输入流对象
B: 调用read()方法读取数据,并把数据显示在控制台
C: 释放资源
举例
FileInputStream fis = new FileInputStream("fis.txt");
int by = 0;
while ((by = fis.read()) != -1) {
System.out.print((char) by);
}
// 释放资源
fis.close();
复制文本文件
// 封装数据源
FileInputStream fis = new FileInputStream("a.txt");
// 封装目的地
FileOutputStream fos = new FileOutputStream("b.txt");
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源(先关谁都行)
fos.close();
fis.close();
一次读取一个字节数组
- int read(byte[] b)
- 举例
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("fis2.txt");
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
// 释放资源
fis.close();
// 把c:\\a.txt内容复制到d:\\b.txt中
FileInputStream fis = new FileInputStream("C:\\a.txt");
FileOutputStream fos = new FileOutputStream("D:\\b.txt");
byte[] bys = new byte[1024];
int len = 0;
while((len = fis.read(bys))!= -1) {
fos.write(bys,0,len);
}
// 释放资源
fos.close();
fis.close();
带缓冲的字节类
通过定义数组的方式确实比以前一次读取一个字节的方式快很多,java提供了带缓冲区的字节类 * 这种类被称为:缓冲区类(高效类)
写数据: BufferedOutputStream
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("bos.txt"));
// 写数据
bos.write("hello".getBytes());
// 释放资源
bos.close();
读数据: BufferedInputStream
- 方式一
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("bos.txt"));
// 读取数据
int by = 0;
while((by=bis.read())!= -1) {
System.out.print((char)by);
}
// 释放资源
bis.close();
- 方式二
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("bos.txt"));
byte[] bys = new byte[1024];
int len = 0;
while((len=bis.read(bys))!= -1) {
System.out.println(new String(bys,0,len));
}
// 释放资源
bis.close();
- 注意:虽然我们有两种方式可以读取,但是请注意这两种方式针对同一个对象在一个代码中只能使用一个。
注意
- 构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了
- 为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是呢,真正的读写操作还得靠基本的流对象实现
IO流分类
- 字节流
- InputStream
- FileInputStream
- BufferedInputStream
- OutputStream
- FileOutputStream
- BufferedOutputStream
- InputStream
- 字符流
- Reader
- FileReader
- BufferedReader
- Writer
- FileWriter
- BufferedWriter
- Reader