[关闭]
@w460461339 2016-11-16T07:08:05.000000Z 字数 3892 阅读 888

Java学习Day9(递归 IO流)

Java基础


妈蛋,终于搞完开题报告了,可以愉快的重新开始Java的学习(当然还要兼顾毕设了…哭)
今天主要学习的是递归和IO流。

1.递归

递归就结合File来说吧。分别为递归的获取某目录下所有以jpg结尾的文件(包含子目录中的)以及递归的删除。
递归规则:

递归要有出口(出口条件)
递归次数不能太多
构造方法不能递归使用

递归编程:

要明确规律,将问题分解为有层次感的小问题,每层的问题都可以用相同的策略解决。
这就是数列里面的S(n+1)=F(S(n))的思想。
或者简单点,分解+合并。
1.1 递归的拿某目录下所有以JPG结尾的文件(包含子目录中的)
  1. import java.io.File;
  2. public class DiguiDemo {
  3. public static void main(String[] args) {
  4. File myFile=new File("demo");
  5. readAllJPG(myFile);
  6. }
  7. public static void readAllJPG(File myFile){
  8. File[] fileArray=myFile.listFiles();
  9. for(File fl:fileArray){
  10. if(fl.isDirectory()){//判断是否是文件夹
  11. readAllJPG(fl);
  12. }else{//终止条件
  13. //获取文件名字,判断字符串是否以.jpg结尾
  14. if(fl.getName().endsWith(".jpg")){
  15. //打印绝对路径
  16. System.out.println(fl.getAbsolutePath());
  17. }
  18. }
  19. }
  20. }
  21. }
1.2递归的删除所有文件以及文件夹
  1. import java.io.File;
  2. public class DiguiDemo {
  3. public static void main(String[] args) {
  4. File myFile=new File("demo");
  5. deleteAll(myFile);
  6. }
  7. public static void deleteAll(File myFile){
  8. File[] fileArray=myFile.listFiles();
  9. if(fileArray!=null){//防止空指针异常
  10. for(File fl:fileArray){
  11. if(fl.isDirectory()){//文件夹就继续进入
  12. deleteAll(fl);
  13. }
  14. else{//文件就删
  15. System.out.println(fl.getName()+"--"+fl.delete());
  16. }
  17. }
  18. }
  19. //最后删除当前文件(记得操作的时候不要打开该文件,不会因为被占用而删不掉)
  20. System.out.println(myFile.getName()+"--"+myFile.delete());
  21. }

2.IO流

IO流按流向分可以分为: 输入 输出
按照类型分有:

字节流:输入 输出
字符流:输入 输出

注意:

a:如果我们没有明确说明按照什么分,默认按照数据类型分。
b:除非文件用windows自带的记事本打开我们能够读懂,才采用字符流,否则建议使用字节流。

下面仅以字节流演示

2.1基本流之写操作

a 创建字节输出流对象
b 调用write方法
c 关闭

  1. package myIOstream;
  2. import java.io.FileNotFoundException;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. public class MyIOStream {
  6. public static void main(String[] args) throws IOException {
  7. //构造方法:直接传入文件的抽象路径也行
  8. //FileOutputStream fos=new FileOutputStream(new File("aa.txt"));
  9. //像楼上这样封装成File对象再传入也行
  10. //另外,若原本没有aa.txt,该构造函数会自动创建
  11. FileOutputStream fos=new FileOutputStream("aa.txt");
  12. //同时,该构造方法会有编译异常,直接抛出就好
  13. fos.write("hello".getBytes());
  14. fos.close();//千万注意关闭
  15. }
  16. }

多次运行会发现,aa.txt中只有一个hello,不会增加。那怎么才能每一次run之后增加呢?

  1. //trur表示每次从当前文档末尾添加,false表示从头覆盖
  2. FileOutputStream fos=new FileOutputStream("aa.txt",true);
2.2基本流之读操作

有两种方法
Way1:一个字节一个字节读。效率太低。

  1. import java.io.FileInputStream;
  2. import java.io.IOException;
  3. public class myInput {
  4. public static void main(String[] args) throws IOException {
  5. FileInputStream fis=new FileInputStream("aa.txt");
  6. int by=0;
  7. //read()返回字节的int表示。读到文档末尾返回-1
  8. while((by=fis.read())!=-1){
  9. System.out.print((char)by);
  10. }
  11. }
  12. }

Way2:一个字节数组一个字节数组的读。

  1. import java.io.FileInputStream;
  2. import java.io.IOException;
  3. public class myInput {
  4. public static void main(String[] args) throws IOException {
  5. FileInputStream fis=new FileInputStream("aa.txt");
  6. byte[] by=new byte[1024];//最好是1024或者其倍数
  7. int len=0;//len用来记录每次读取的字节数
  8. //此时read(byte[] by)返回读入了多少个字节
  9. while((len=fis.read(by))!=-1){
  10. //一定要用len这种方式。
  11. System.out.println(new String(by,0,len));
  12. }
  13. }
  14. }
2.3高速流之读写操作

BufferedInputStream以及BufferedOutputStream都是高速的读写IO流。之所以高速,是因为其内部利用缓存,每次积累一定量的数据后再对底层进行操作。下面两个一起演示。

  1. import java.io.BufferedInputStream;
  2. import java.io.BufferedOutputStream;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. public class MybufferedIO {
  7. /**
  8. * 源数据:
  9. * 当前目录下aa.txt
  10. * 目标数据:
  11. * D盘根目录下bb.txt
  12. * @throws IOException
  13. */
  14. public static void main(String[] args) throws IOException {
  15. //创建读 写对象
  16. BufferedInputStream bis=new BufferedInputStream(
  17. new FileInputStream("aa.txt"));
  18. BufferedOutputStream bos=new BufferedOutputStream(
  19. new FileOutputStream("D:\\bb.txt",true));
  20. byte[] by=new byte[1024];
  21. int len=0;
  22. while((len=bis.read(by))!=-1){
  23. System.out.println(new String(by,0,len));
  24. bos.write(by, 0, len);
  25. //不同系统换行标识符不同,尽量把\r\n都写上
  26. bos.write("\r\n".getBytes());
  27. }
  28. bos.close();//一定要记得关
  29. bis.close();
  30. }
  31. }

这里演示了BufferedInputStream以及BufferedOutputStream的用法以及如何进行数据的复制。其中BufferedInputStream和BufferedOutputStream的构造函数可以指定缓冲区大小,但一般都用默认的。
另外的对图像和对视频文件的复制这里不演示了。

3.Q&A

a:创建字节输出流对象做了几件事情?
三件事:

1、若文件不存在,调用系统功能在指定位置创建文件
2、创建字节输出流对象
3、将字节输出流对象指向该文件。

b:为什么要close()?

1、将字节输出/出路流对象变为垃圾,方便回收资源
2、释放与此流有关的系统资源。

c:如何实现数据的换行?

不同系统换行不同,把\r\n都写了保险点。

d:如何实现数据的追加写入?

FileOutputStream的构造函数之一为:
    FileOutputStream(String name, boolean append)或者
    FileOutputStream(File file, boolean append)
后面的boolean变量为true,表示从文档尾部添加,实现追加写入。不写或者false,则从文档头部实现覆盖写入。

e:中文字符识别

中文字符由两个字节组成,第一个字节一定为负数,通过识别负数即可知道是否需要将后续字节拼起来,成为一个完整的字。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注