文件操作——IO

一、文件的介绍


平时说的文件一般都是指存储在硬盘上的普通文件

形如txt,jpg.mp4.rar等这些文件都可以认为是普通文件.他们都是在硬盘上存储的。

在计算机中文件不只是包含普通文件还可以包含目录(把目录成为目录文件)。目录就是文件夹。

操作系统中,还会使用文件来描述一些其它的硬件设备或者软件资源。

文件的分类:
1.文本文件:里面存储的是字符
2.二进制文件:里面存储的是字节

文本文件本质上也是存字节的但是文本文件中,相邻的字节在一起正好能构成一个个的字符
而二进制文件中字节和字节之间就完全没有关系。
判定一个文件是文本和二进制的方法:用记事本打开如果打开之后是乱码就是二进制不是乱码就是文本。


二、【重点】关于目录结构:
计算机里保存管理文件是通过操作系统中的“文件系统”这样的模块来负责的,文件系统中一般是通过“树形”结构来组织磁盘上的目录和文件的。
在操作系统中通过“路径”这样的概念来描述一个具体文件/目录的位置。

路径的两种描述风格:
1.绝对路径:以盘符开头的。
       例如D:\program\jdk\bin\javac.exe
2.相对路径:.或者..开头的其中.表示当前路径..表示当前路径的父目录(上级路径)
例如:以D:\program\jdk\bin为基准目录找到javac.exe
用相对路径就可以表示为:./javac.exe
以D:\program基准目录找到javac.exe
用相对路径就可以表示为:.用相对路径就可以表示为:./jdk/bin/javac.exe

相对路径必须要有一个基准目录,相对路径就是从基准目录出发按照一个什么样的路径找到对应的文件。

三、Java中操作文件:

1.文件系统相关的操作:
指的是通过“文件资源管理器”能够完成的一些功能。(列出目录中有哪些内容、创建文件、创建目录、删除文件、重命名文件.....)
在Java中提供了一个File类。通过这个类来完成上述操作。首先这个File类就描述了一个文件/目录,基于这个对象就可以实现上面的功能。
File的构造方法能够传入一个路径来指定一个文件.这个路径可以是绝对路径也可以是相对路径。

构造好对象之后就可以通过方法来完成一些具体的功能

    public static void main(String[] args) throws IOException {
        //文件的创建和删除
        File f=new File("./test.txt");
        System.out.println(f.exists());//检查文件是否存在
        System.out.println("创建文件");
        f.createNewFile();//创建文件操作
        System.out.println("创建文件操作");
        System.out.println(f.exists());//检查文件是否存在
    }

    public static void main(String[] args) {
        //File f=new File("d:/test.txt");
        File f=new File("./test.txt");//找当前代码路径下的
        System.out.println(f.exists());//判断是否存在
        System.out.println(f.isDirectory());//判断是否是目录
        System.out.println(f.isFile());//判断是否是文件
    }

 

    public static void main(String[] args) {
        File f=new File("./test.txt");
        f.delete();//删除文件
    }
    public static void main(String[] args) {
        File f=new File("./aaa/bbb/ccc/ddd");
        f.mkdirs();//创建多级目录
        System.out.println(f.isDirectory());

    }
    public static void main1(String[] args) {
        File f=new File("./aaa");
        f.mkdir();//把f对应的目录创建出来,只能创建一级目录
        System.out.println(f.isDirectory());//判断是否是目录
    }
  public static void main(String[] args) {
        File f=new File("./");
        System.out.println(Arrays.toString(f.list()));//f.list()列出目录内容的操作
    }

    public static void main(String[] args) {
        File f=new File("./");
        System.out.println(Arrays.toString(f.listFiles()));//f.listFiles()列出目录文件的操作
    }

public static void main(String[] args) {
        File f=new File(" ./aaa");
        File f2=new File("./eee");
        f.renameTo(f2);//把f名字改成f2的名字
    }

2.文件内容相关的操作: 

1)打开文件        2)读文件        3)写文件        4)关闭文件

 

 FileNotFoundException是IOException的子类

一、使用字节流读文件操作:

1、一次读一个字节:

public static void main(String[] args) throws FileNotFoundException {
        //构造方法中需要指定打开文件的路径
        //此处的路径可以是绝对路径,也可以是相对路径,还可以是File对象
        try {
            //1、创建对象,同时也在打开文件
            InputStream inputStream=new FileInputStream("d:/test.txt");
            //2、尝试一个一个字节的读,把整个文件都读完
            while(true){
                int b=inputStream.read();//当返回值为-1时证明读到了文件末尾
                if(b==-1){
                    //读到了文件末尾
                    break;
                }
                System.out.println(b);
            }
            //3、读完之后关闭文件,释放资源
            inputStream.close();
        } catch (IOException e) { 
            e.printStackTrace();
        }
    }

但是上面不太靠谱,万一read操作出现异常,就会直接触发catch代码,导致close无法执行

更好的办法是将close放到finall里,这样无论如何都会执行~

public static void main(String[] args) {
        //构造方法中需要指定打开文件的路径
        //此处的路径可以是绝对路径,也可以是相对路径,还可以是File对象
        InputStream inputStream=null;
        try {
            //1、创建对象,同时也在打开文件
            inputStream=new FileInputStream("d:/test.txt");
            //2、尝试一个一个字节的读,把整个文件都读完
            while(true){
                int b=inputStream.read();//当返回值为-1时证明读到了文件末尾
                if(b==-1){
                    //读到了文件末尾
                    break;
                }
                System.out.println(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //3、读完之后关闭文件,释放资源
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

但是上述操作有点啰嗦~可以使用try  with  resources语法,此时try执行完后就会自动调用close

try(InputStream inputStream=new FileInputStream("d;/test.txt")) {//因为所有的流对象都实现了Closeable这个接口,所以可以放到try()中
            while(true){
                int b=inputStream.read();
                if(b==-1){
                    break;
                }
                System.out.println(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

2、一次读若干个字节:

try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
            //一次读若干个字节
            while (true) {
                byte[] buffer = new byte[1024];
                int len = inputStream.read(buffer);//这个操作是把读出来的结果放到buffer这个数组中了,相当于是使用参数来表示这个方法的返回值,这种做法称为“输出型参数”
                if (len == -1) {
                    break;//如果返回-1,证明读完了
                }
                for (int i = 0; i < len; i++) {
                    System.out.println(buffer[i]);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

二、使用字节流写文件操作

1、一次写一个字节:

public static void main(String[] args) throws FileNotFoundException {
        try(OutputStream outputStream=new FileOutputStream("d:/test.txt")) {
            outputStream.write(97);//一个方法写一个字节
            outputStream.write(98);
            outputStream.write(99);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2、一次写若干个字节:

try(OutputStream outputStream=new FileOutputStream("d:/test.txt")) {
            byte[] buffer=new byte[]{97,98,99};
            outputStream.write(buffer);//一个方法写多个字节
        } catch (IOException e) {
            e.printStackTrace();
        }

注意:每次按照写方式打开文件,都会清空原有文件的内容,清空旧的内容,再从起始位置往后写

三、按照字符来读

一次读若干个字符:

public static void main(String[] args) throws FileNotFoundException {
        try(Reader reader=new FileReader("d:/test.txt")) {
            //按照字符来读
            while(true){
                char[] buffer=new char[1024];
                int len=reader.read(buffer);
                if(len==-1){
                    break;
                }
                for (int i = 0; i < len; i++) {
                    System.out.println(buffer[i]);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

四、按照字符来写

 public static void main(String[] args) throws FileNotFoundException {
        try(Writer writer=new FileWriter("d:/test.txt")) {
            writer.write("xyz");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 四、文件操作的案例

1、扫描指定目录,并找到名称中包含指定字符的所有指定文件(不包含目录),并且后续询问用户是否要删除该文件

即用户输入一个目录,再输入一个要删除的文件名

//实现查找文件并删除
    public static void main(String[] args) {
        //1、先输入要扫描的目录。以及要删除的文件名
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要扫描的路径:");
        String rootDirPath=scanner.next();
        System.out.println("请输入要删除的文件名:");
        String toDeleteName=scanner.next();
        File rootDir=new File(rootDirPath);//根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径
        if(!rootDir.isDirectory()){
            System.out.println("输入的扫描路径有误!");
            return;
        }
        //2、遍历目录,把指定目录中的所有文件和子目录都遍历一遍,从而找到要删除的文件
        //通过这个方法来实现递归遍历并删除的操作
        scanDir(rootDir,toDeleteName);
    }

    private static void scanDir(File rootDir, String toDeleteName) {
        //1、先列出rootDir中都有哪些内容
        File[] files=rootDir.listFiles();
        if(files==null){
            //rootDir是一个空目录
            return;
        }
        //2、遍历当前列出的这些内容,如果是普通文件,就检测文件名是否是要删除的文件
        //如果是目录,就递归的进行遍历
        for(File f:files){
            if(f.isFile()){
                //普通文件的情况
                if(f.getName().contains(toDeleteName)){
                    //不要求名字完全一样,只是要文件名中包含了关键字即可删除
                    //进行删除操作
                    deleteFile(f);
                }
            }else if(f.isDirectory()){
                //目录就递归的进行遍历
                scanDir(f,toDeleteName);
            }
        }
    }

    private static void deleteFile(File f) {
        try {
            System.out.println(f.getCanonicalPath()+"确认要删除文件嘛?(Y/N)");//getAbsolutePath() 返回 File 对象的绝对路径
            Scanner scanner=new Scanner(System.in);
            String choice=scanner.next();
            if(choice.equals("Y")||choice.equals("y")){
                f.delete();
                System.out.println("文件删除成功!");
            }else{
                System.out.println("文件放弃删除!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2、进行普通文件的复制

即需要让用户指定两个文件路径,一个是原路径(被复制的文件),一个是目标路径(复制后生成的文件)。打开原路径的文件,读取里面的内容并写入到目标文件

 public static void main(String[] args) throws FileNotFoundException {
        //1、输入两个路径
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要拷贝的源路径:");
        String src=scanner.next();
        System.out.println("请输入要拷贝的目标路径:");
        String dest=scanner.next();
        File srcFile=new File(src);
        if(!srcFile.isFile()){
            System.out.println("输入的源路径不正确!");
            return;
        }desc
        //此处不太需要检查目标文件是否存在,OutputStream写文件的时候能够自动创建不存在的文件
        //2、读取文件,拷贝到目标文件中
        try(InputStream inputStream=new FileInputStream(src)){
            try(OutputStream outputStream=new FileOutputStream(dest)){
                //把inputStream中的数据读出来,写入到outputStream中
                byte[] buffer=new byte[1024];
                while(true){
                    int len=inputStream.read(buffer);
                    if(len==-1){//读取完毕
                        break;
                    }
                    //写的时候,不能把整个buffer都写进去,毕竟buffer可能是只有一部分才是有效数据
                    outputStream.write(buffer,0,len);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3、扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

即进行文件内容的查找,先输入一个路径,再输入一个要查找的文件内容的“关键词”,递归遍历文件,找到看哪个文件里的内容包含了关键词,就 把对应的文件路径打印出来

思路:先递归遍历文件,针对每个文件都打开并读取内容,在进行字符串查找

public static void main(String[] args) throws IOException {
        //1、输入要扫描的文件路径
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要扫描的路径:");
        String rootDirPath=scanner.next();
        System.out.println("请输入要查询的关键词:");
        String word=scanner.next();
        File rootDir=new File(rootDirPath);
        if(!rootDir.isDirectory()){
            System.out.println("输入的路径为非法!");
            return;
        }
        //2、递归进行遍历
        scanDir(rootDir,word);
    }

    private static void scanDir(File rootDir, String word) throws IOException {
        //1、先列出rootDir中都有哪些内容
        File[] files=rootDir.listFiles();
        if(files==null){
            return;
        }
        //2、遍历每个元素,针对普通文件和目录分别进行处理
        for(File f:files){
            if(f.isFile()){
                //针对文件进行内容查找
                if(containsWord(f,word)){
                    System.out.println(f.getCanonicalPath());
                }
            }else if(f.isDirectory()){
                //针对目录进行递归
                scanDir(f,word);
            }
        }
    }

    private static boolean containsWord(File f, String word) throws FileNotFoundException {
        StringBuilder stringBuilder=new StringBuilder();
        //把f中的内容都读出来,放到一个StringBuilder中
        try(Reader reader =new FileReader(f)) {
            char[]buffer=new char[1024];
            while(true){
                int len=reader.read(buffer);
                if(len==-1){
                    break;
                }
                //把这一段读到的结果,放到StringBuilder中
                stringBuilder.append(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        //indexOf返回的是子串的下标,如果word在stringBuilder中不存在,则返回下标为-1
        return stringBuilder.indexOf(word)!=-1;//判断是不是子串
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值