在学习IO流之前我们今天先学习了递归。
递归
递归:就是在方法定义中调用方法本身的现象。 在使用递归时,必须有一个明确的递归结束条件,称为递归出口。
下面举个例子:
1.用递归来实现斐波那契额数列,如1,1,2,3,5,8,13…,输出前20项的和。
public static int fib(int n){//n表示项数
if(n==1||n==2){
return 1;
}else{
return fib(n-1)+fib(n-2);
}
}
public static void main(String[] args) {
System.out.println(fib(20)); //结果为6765。
}
2.练习:用递归删除带内容(文件)的目录
public static void main(String[] args) {
File f = new File("F:\\File练习题");
method(f);
}
public static void method(File file) {
File[] listFiles = file.listFiles();
for (File file1 : listFiles) {
if(file1!=null) { //先判断文件对象是否为空,避免出现空指针异常
if(file1.isDirectory()) { //然后再判断该文件对象是否是目录,如果是目录则调用本身函数(递归),逐个找到文件并删除
method(file1);
}else {
file1.delete();
}
}
}
}
I/0流
1.I/O流的分类:
流向:
输入流 读取数据
输出流 写入数据
数据类型:
字节流:
字节输入流 读取数据 InputStream
字节输出流 写入数据 OutputStream
字符流:
字符输入流 读取数据 Reader
字符输出流 写入数据 Writer
注意:一般我们在探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况按照数据类型来分。
今天我们主要学习了字节流。
字节流
- FileOutputStream(输出流)的构造器:
FileOutputStream(File file)
创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(String name)
创建文件输出流以指定的名称写入文件。
FileOutputStream(File file, boolean append)
创建文件输出流以写入由指定的 File对象表示的文件。 默认是false 也就是说默认是不追加在文字的末尾的。
File f = new File("F:\\File练习题");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);//创建文件输出流写入指定文件对象所表示的文件中,如果文件不存在则自动创建
fos.write("hello world".getBytes());
fos.write(" 你好!".getBytes());
} catch (FileNotFoundException e) {
//文件可能找不到的情况
e.printStackTrace();
} catch (IOException e) {
//输入输出异常
e.printStackTrace();
}finally {
try {
if(fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.用字节流来实现写入操作。
public void write(int b);写一个字节
public void write(byte[] b);写一个字节数组
public void write(byte[] b,int off,int len);写一个字节数组的一部分
例如:
File f = new File("F:\\File练习题");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
byte[] bs = {97,88,41,36,77,127};
os.write(bs, 0,bs.length);//len是字节的长度 off字节数组的起始下标
os.write(bs);
} catch (FileNotFoundException e) {
//文件可能找不到的情况
e.printStackTrace();
} catch (IOException e) {
//输入输出异常
e.printStackTrace();
}finally {
try {
if(fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
FileInputStream(字节输入流/读取数据)的操作步骤:
A.创建字节输入流对象
B.调用read()方法读取操作,并把数据显示在控制台中
C.释放资源
读取方式:
A.int read():一次读取一个字节
B.int read(byte[] b):一次读取一个字节数组
C.int read(byte[] b,int off,int len):一次读取一个部分字节数组
例如:
1.
//每次只读取一个字节
FileInputStream fis = null;
try {
fis = new FileInputStream("a.txt");
int by = 0;
while((by = fis.read())!=-1){ //循环读取,读取完毕则返回-1;
System.out.println((char)by); //中文不可用,会输出乱码-->此处会抛出 IOException,需要try catch
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fis!=null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
int read(byte[] b):一次读取一个字节数组。
FileInputStream fis = null;
byte[] b = new byte[1024];
try {
fis = new FileInputStream("a.txt");
int len = 0;
while((len = fis.read(b))!=-1) {
System.out.print(new String(b,0,len));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(fis!=null) {
fis.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3.复制文件。
若数据源 目的地是相同的,那么复制的文件必须要重命名,因为不重命名叫覆盖。
数据源:从哪里来,即读取文件数据。
目的地:到哪里去,即将读取出的文件数据写入目标文件中。
例子:
FileInputStream fis = null;
FileOutputStream fos = null;
byte[] bs = new byte[1024];
try {
fis = new FileInputStream("a.txt");//读取数据(输入流)
fos = new FileOutputStream("b.txt");//写入数据(输出流)
int len = 0;
//边读边写
while((len = fis.read(bs)) != -1) {
fos.write(bs);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}