zoukankan      html  css  js  c++  java
  • 零基础学习java------day16-----文件,递归,IO流(字节流读写数据)

    1.File

    1.1 构造方法(只是创建已经存在文件的对象,并不能创建没有的文件)

    (1)public File(String pathname)

    (2)public File(String parent, String child)

    (3)public File(File parent, String child)

    public class FileDemo1 {
        public static void main(String[] args) {
            File f = new File("e:/a/b");
            System.out.println(f.exists()); //true
            File f1 = new File("e:/G09 result/","H2O"); //此处result后的“/”号有无都可以
            System.out.println(f1.exists()); //true
            File f2 = new File(f1,"H2O.out");
            System.out.println(f2.exists());//true
        }
    }

    1.2 File类成员方法

    1.2.1 创建删除重命名功能

    (1)创建功能  

      public boolean createNewFile()       创建文件
      public boolean mkdir()                     创建单层文件夹
      public boolean mkdirs()                   创建多层文件夹

    (2)删除功能

      public boolean delete()                    删除文件或文件夹(文件夹中有内容无法删除)

    (3)重命名功能 

      public boolean renameTo(File dest)   重命名(移动)

    public class FileDemo2 {
        public static void main(String[] args) {
            try {
                File f = new File("e:/G09 result/H2O/t.txt");//创建文件的时候,目录必须存在
                boolean b = f.createNewFile();
                new File("e:/a").mkdir(); //在盘创建了a文件夹
                new File("e:/a/b/c/d").mkdirs();//创建了多层文件夹,此对象代表d这个文件夹
                File f1 = new File("e:/123");
                f1.createNewFile();//得到的是一个文件,文件可以没有后缀名
                File f2 = new File("e:/789.txt");
                f2.mkdir();//得到的是一个文件夹
                f1.delete();
                f2.delete(); // 如果文件夹中有内容是不能被删除的
                f.renameTo(new File("d:/haha.txt")); //将e:/G09 result/H2O/t.txt文件移动到d盘,并重命名为haha.txt
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    1.2.2 判断功能

    (1)public boolean isDirectory():是否是目录

    (2)public boolean isFile():是否是文件

    (3)public boolean exists():是否存在

    (4)public boolean canRead():是否可读

    (5)public boolean canWrite():是否可写

    (6)public boolean isHidden():   是否隐藏

    public class FileDemo3 {
        public static void main(String[] args) {
            File f = new File("e:/a");
            System.out.println(f.exists()); //true
            System.out.println(f.isDirectory());//true
            System.out.println(f.isFile());//false
            System.out.println(f.canRead()); //true
            System.out.println(f.canWrite()); //true
            System.out.println(f.isHidden()); //false
        }
    }

    1.2.3  获取功能

    a . 基本获取功能

    (1)public String getAbsolutePath():获取绝对路径

    (2)public String getPath():              获取相对路径

    (3)public String getName():            获取文件名

    (4)public long  length():                  获取字节数

    (5)public long lastModified:            获取最后修改时间

    public class FileDemo4 {
        public static void main(String[] args) throws IOException {
            File f1 = new File("忽然.txt");
            f1.createNewFile();
            System.out.println(f1.getAbsolutePath());//E:developmentworkspacejavajavasejavase忽然.txt
            System.out.println(f1.getPath());//忽然.txt
            System.out.println(f1.getName());//忽然.txt
            System.out.println(f1.length());
            System.out.println(f1.lastModified());//1566540753201
            //先将long类型的毫秒值转为date类型的时间,然后再讲此时间转为特定格式的时间
            System.out.println(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(f1.lastModified())));
        }
    }

    b . 高级获取功能

    (1)public String[ ]  list():                    获取所有子文件名称(返回值类型为字符串数组)

    (2)public File[ ] listFiles():                获取所有子文件对象  (返回值类型为文件类型数组)        

    public class FileDemo5 {
        public static void main(String[] args) {
            File f = new File("E:\exercise");
            System.out.println(f.list());  //[Ljava.lang.String;@279f2327
            System.out.println(Arrays.toString(f.list()));//这样转化后就能打印数组了
            File[] listFiles = f.listFiles();
            System.out.println(f.listFiles());//[Ljava.io.File;@2ff4acd0,需要将其遍历出来
            for(File file:listFiles) {
                System.out.println(file);
            }
        }
    }

    练习  查询单层文件夹下所有以后缀名(.jpg))结尾的文件,此处,我要查询的文件夹如下:

    法一:

    public class FindFile {
        public static void main(String[] args) {
            getFile("E:\exercise",".jpg");
        }
        public static void getFile(String path,String suffix) {
            File f = new File(path);
            File[] listFile = f.listFiles();
            for (File file : listFile) {
           //除了判断后缀,还要判断是不是文件,有大写文件的话,转为小写
    if(file.isFile() && file.getName().toLowerCase().endsWith(suffix)) { System.out.println(file.getAbsolutePath()); } } } }

    法二(使用过滤器)

    public class FindFile {
        public static void main(String[] args) {
            getFile("E:\exercise",".jpg");
        }
        public static void getFile(String path,String suffix) {
            File f = new File(path);
         // 带有过滤器为参数的listFiles方法,这里使用了匿名函数来创建过滤器对象
            File[] files = f.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    File f1 = new File(dir,name);
                    if(f1.isFile()&&f1.getName().toLowerCase().endsWith(suffix)) {
                        return true;
                    }
                    return false;
                }
            });
            for (File file : files) {
                System.out.println(file.getAbsolutePath());
            }
        }        
    }

     2. 递归

     2.1 递归的思想概述

       方法定义中调用本身的现象。

     注意事项:

      递归要有出口,否则就是死递归;次数不能太多,否则内存会溢出;构造方法不能递归使用

    2.2 递归的思想

      找到出口;找到规律

    2.3 递归练习

    1. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到三个月后每个月又生一对兔子,假如兔子都不死,问第十个月兔子对数为多少?

    本题的本质是斐波那契数列,如下图:

    第一个月时,有一对兔子(刚生下来为小兔子,过了一个月后就变成大兔子,再过一个月就能生小兔子),第二个月是总的兔子数还是为1,但此时小兔子变成了大兔子,第三个月大兔子生了一对小兔子,所以第三个月有2对兔子(一大一小),依次类推下去可得斐波那契数列(正如图上的sum行)

    public class BornRabbit {
        public static void main(String[] args) {
            System.out.println("10个月后兔子对数:"+ rabbitNumber(10));
        }
        public static int rabbitNumber(int month) {
            if(month==1 || month==2) {
                return 1;
            }else {
                return rabbitNumber(month-1)+rabbitNumber(month-2);
            }
        }
    }

    2.小猴子第一天摘下若干桃子,当即吃掉一半,又多吃一个,第二天早上又将剩下的桃子吃掉一半,又多吃一个,以后每天早上吃前一天剩下的一半以及另一个。到第10天早上猴子想再吃时发现,只剩下一个桃子了,问第一天猴子共摘了多少个桃子?

     规律如下图

    public class Monkey {
        public static void main(String[] args) {
            System.out.println(eatPeach(1));
        }
        public static int eatPeach(int day) {
            if(day==10) {
                return 1;
            }else {
                return 2*(eatPeach(day+1)+1);
            }
        }
    }

     3. 递归查找文件(文件夹有多层)

    public class RecursionFindFiles {
        public static void main(String[] args) {
            findAllFiles("E:/exercise",".jpg");
        }
        public static void findAllFiles(String path, String suffix) {
            File f = new File(path);
            //如果传入的路径为文件
            if(f.isFile()) {
                if(f.getName().toLowerCase().endsWith(suffix));{
                    System.out.println(f.getAbsolutePath());
                }
            }else {   //是文件
                //获取所有子文件    
                File[] listFiles = f.listFiles();
                if(listFiles!=null && listFiles.length>0) {
                    for (File file : listFiles) {
                        findAllFiles(file.getAbsolutePath(),suffix);
                    }
                }
            }
        }
    }

     变形:递归删除文件夹以及其中的所有文件

    public class RecursionDelete {
        public static void main(String[] args) {
            findAllFiles("E:/a");
        }
        public static void findAllFiles(String path) {
            File f = new File(path);
            //如果传入的路径为文件
            if(f.isFile()) {
                f.delete();
            }else {   //是文件
                //获取所有子文件    
                File[] listFiles = f.listFiles();
                if(listFiles!=null && listFiles.length>0) {
                    for (File file : listFiles) {
                        findAllFiles(file.getAbsolutePath());
                    }
                }
                f.delete();
            }
        }
    }

    3. IO流

    3.1 IO流的概述

    IO流用来处理设备之间的数据传输(上传文件和下载文件),Java对数据的操作是通过流的方式,此外java用于流的操作对象都在IO包中

    3.2 IO流的分类

    (1)按照数据流向

      输入流: 读入数据

      输出流:写出数据

    (2)按照数据类型

      字节流,字符流

      一个汉字若按字节流处理,需要处理3次(utf8编码中一个汉字3个字节),若用字符流来处理只需要一次,但字符流一般只能用来处理文本文件,如图片就不能处理,但字节流(任何文件都可以处理)可以,所以字节流较字符流使用范围更广

    (3)什么情况下使用哪种流呢?

      如果数据所在的文件通过windows自带的记事本打开并能读里面的内容,就用字符流。其他用字节流

    3.3 IO流常用基类

    (1)字节流的抽象基类:

      InputStream,OutputStream

    (2)字符流的抽象基类

      Reader  ,     Writer

    注意:由这四个类派生出来的子类名称都是以其父类名作为类名的后缀

    如:InputStream的子类FileInputStream

      Reader的子类FileReader

    3.4 字节流写数据(FileOutputStream)

    3.41 FileOutputStream的构造方法:

    (1)FileOutputStream(File, file)

    (2)FileOutputStream(String name)   //一般用第二种,方便点

    3.4.2  FileOutputStream的成员方法

    (1)public void write(int b)

    (2)public void write(byte[ ] b)

    (3)public void write(byte[ ] b,int  off, int len)  

    public class FileOutputStreamDemo {
        public static void main(String[] args) {
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream("d:/haha.txt");
                fos.write(97);
                fos.write(98);
                fos.write(99);
            } catch (Exception e) {
                e.printStackTrace();
            }finally {   // 关流,即关闭文件
                if(fos != null) {  //此处要判断下不为null
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    运行结果:d盘中的haha.txt写入了abc

    但是怎样写入一字符串呢?=====>将字符串转成Byte,改用第二或第三个成员方法

    fos.write("忽然就流出泪来".getBytes());//此代码紧接着fos.write(99)哪行写
    fos.write("哈哈忽然间想要听到他的声音".getBytes(),6,33);//后面两个int值第一个为偏移量,第二个为从偏移量位置开始写入数据的长度,这里长度以Byte为单位

    运行结果:abc忽然就流出泪来,忽然间想要听到她的声音

    有上面代码可知,手动关流写起来比较麻烦,JDK1.7以后提供了自动关流的方法,格式如下:

    try(流的定义语句){
    
    }catch(){
    
    }

    注意:另外创建一个流,并将数据写入原先有数据的文件,会将原先的数据覆盖掉)(如上面例子中haha.txt原先若有内容则会覆盖掉),但一个流中依次写入的数据,后者写入不会覆盖前者写入的数据

    让其不覆盖院线数据的方法是:在利用构造方法创建对象时传两个参数,除了路径再传个True(默认是false),这样就不会覆盖原先的数据了

      当将上诉第5行代码换成如下代码时,运行多次程序,会得到多句同样的结果,不会覆盖(原先无论运行几次都是一句话)

    fos = new FileOutputStream("d:/haha.txt",true);

    3.5 字节流读取数据(FileInputStream)

    3.5.1  FileInputStream的构造方法

    (1)FileInputStream(File file)

    (2)FileInputStream(String)  //一般用第二种,方便点

    3.5.1  FileInputStream的成员方法

    (1)public int read()         每次读取一个字节并 返回读取一个字节所对应的编码

    (2)public int read(byte[] b)   :每次读取数组的长度个字节,返回读回来的长度(实际读取的内容)

    第二个成员方法返回的是buffer(缓存区)  b的长度          

     1 public class FileInputStreamDemo {
     2     public static void main(String[] args) {
     3         try(
     4                 FileInputStream fis = new FileInputStream("d:/a.txt"); //啊的内容为 ab
     5                 ){
     6             System.out.println(fis.read()); //97
     7             System.out.println(fis.read());//98
     8             System.out.println(fis.read());//-1 可见当没内容可读取的时候,返回的是-1
     9         } catch (Exception e) {
    10             e.printStackTrace();
    11         }
    12     }
    13 }

     若将a.txt的内容改为abc大,那么这个中文字“大”怎么读取出来呢?,代码如下

    在上面第8行代码后加如下代码

    1     int d = fis.read();
    2     int e = fis.read();
    3     int f = fis.read();
    4     // 创建一个Bytes数组,将上面三个字节平成一个byte数组
    5     byte[] bs = new byte[] {(byte)d,(byte)e,(byte)f};
    6     System.out.println(bs);//[B@279f2327
    7     System.out.println(new String(bs));//

     这样一个字节一个字节读取很费经,可以直接1kb的读取,要想1字节的话可以用for循环读取,循环控制条件就是读取数据返回值为-1

    若a文件内容还是为”abc大",这次换成一次性读取1kb,代码如下

    public class FileInputStreamDemo {
        public static void main(String[] args) {
            try(
                    FileInputStream fis = new FileInputStream("d:/a.txt"); //啊的内容为 ab
                    ){
                System.out.println(fis.read()); //97
                System.out.println(fis.read());//98
                System.out.println(fis.read());//99
                byte[] bs1 = new byte[1024]; //数组在每个位置的默认值为0,转为字符串就是空格
                fis.read(bs1);
                System.out.println(new String(bs1)); //将byte数组转为字符串打印出来
                System.out.println(new String(bs1).length());//1022 字符串的长度,说明其将空格也读取出来了
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    字符串长度为1022的由来:空格长度为1024-3=1021,一个汉字(大)长度为1,所以字符串长度为1022+1=1023

    怎样让其读取的内容为实际的长度呢?======>让第二个成员方法接收返回值,其返回的是真实的长度

    如将上面代码fis.read(bs1)改为System.out.println(fis.read(bs1)),打印的结果为3,可见返回的是真实读取的字节数

    下例中把文件的内容为:没有人在热河里谈恋爱
    public class FileInputStreamDemo1 {
        public static void main(String[] args) {
            try(
                    FileInputStream fis = new FileInputStream("d:/b.txt"); //啊的内容为 ab
                    ){
                byte[] bs1 = new byte[1024];
                int len;
                while((len = fis.read(bs1))!=-1) {
                    System.out.println(new String(bs1,0,len));//没有人在热河里谈恋爱
                    System.out.println(new String(bs1,0,len).length());//10
                }            
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    由结果可知,读取的内容是实际的长度,并不会将空格也读出来

    拷贝文件,比如将"E:/exercise/haha/天空之城.jpg"拷贝到"E:/exercise/haha/热河.jpg"

    public class CopyFile {
        public static void main(String[] args) {
            try(
                    FileInputStream fis = new FileInputStream("E:/exercise/haha/天空之城.jpg");
                    FileOutputStream fos = new FileOutputStream("E:/exercise/haha/热河.jpg");
                    ) {
                byte[] bs = new byte[1024];
                int len;
                while((len = fis.read(bs)) != -1) {  //读取数据,当返回值为-1时,表示读取完毕
                    fos.write(bs,0,len);  //写入
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    vue路由传参页面刷新参数丢失问题解决方案
    理解MVC,MVP 和 MVVM
    HTTPS用的是对称加密还是非对称加密?
    元素显示隐藏的9种思路
    CSS中层叠上下文
    DOM盒模型和位置 client offset scroll 和滚动的关系
    css重点知识和bug解决方法
    你可能不知道的CSS
    如何在 React 中优雅的写 CSS?
    html5不常用标签应用场景
  • 原文地址:https://www.cnblogs.com/jj1106/p/11397330.html
Copyright © 2011-2022 走看看