文件IO详解

1.路径

相对路径:目录起点为当前工作位置 可以使用./代替

比如当前工作目录为C:/ 那么相对路径就可以写成./code/ 其完整意思为:C:/code 

../表示返回上一级路径  比如当前目录在./code/tmp 使用../code就可以返回上一级code目录下

绝对路径:完整的路径地址

文件分类:

文本文件:存放的是文本-----字符串  每一个字符对应一个数字

二进制文件:存放的是二进制数据 没有任何限制

IO相关方法

    public static void main(String[] args) throws IOException {
        //创建一个文件
        File file = new File("./text.txt");

        //创建一个文件夹  mkdir只能创建一级目录
        File file1 = new File("./aaa");
        file1.mkdir();

        //mkdirs 可以创建多级目录
        File file2 = new File("./aaa/bbb/ccc");
        file2.mkdirs();

        //如果已经有此文件了 则创建失败
        System.out.println(file.createNewFile());

        //文件是否存在
        System.out.println(file.exists());

        //是否是一个文件
        System.out.println("是否是一个文件:"+file2.isFile());

        //是否是一个文件夹
        System.out.println(file.isDirectory()); //在本地IDEA的基础上的路径 ./aaa/bbb/ccc

        //得到文件的相对路径
        System.out.println("file2相对路径:"+file2.getPath()); //D:\code\review\review\IOoperation\.\aaa\bbb\ccc

        //得到文件的绝对路径
        System.out.println("file2绝对路径:"+file2.getAbsoluteFile());

        System.out.println(file.getName());

        //删除文件夹 --- 文件夹里的内容必须是空的才能使用delete方法删除
        File file3 = new File("./aaa/bbb/ccc");
        System.out.println(file3.delete());
    }
  1. mkdir只能创建一级目录  mkdirs可以创建多级目录
  2. 当使用delete删除文件夹时,文件夹下必须没有任何内容才能被删除,否则删除失败
文件流:
字节流

操作二进制数据

InputSteam OutputStream / FileInputStream FileOutputStream


读文件:

 //读文件
        InputStream inputStream = new FileInputStream("./text.txt");

        //字节字节 无参情况下 一次读一个字节
        while(true){
            //返回值为int 因为要用-1来表示文件被读完
            int b = inputStream.read();
            //当为-1时结束读
            if(b == (char)-1){
                break;
            }
            System.out.print(b); //得到字符ASCII码值
        }

如果是无参的话,一次读一个字节,如果想一次多读,可以给定一个字节数组

read()方法返回的是int类型 当为-1时结束读操作


写文件:

 //写操作
        File outputFile = new File("./text2.txt");
        outputFile.createNewFile();
        OutputStream outputStream = new FileOutputStream(outputFile);
        //outputStream.write(97);
        //outputStream.write(98);
        //outputStream.write(99);
        //outputStream.write(100);
        //默认情况下 对于outputSteam来说,每重新打开一个文件时 会先清空里面的内容 如果不想清空 想追加在其后面 可以使用追加流

        String res = "Hello Word";
        //字符串可以直接转字节数组
        int[] arr = {1,2,3};
        outputStream.write(1 + '0');  //会写入答案会转成byte  想写入数组就需要+'0'
    }

需要注意的是,使用ouputStream时,每重新打开一次写的文件,都会先清空内容,如果想追加在内容后面写时,我们可以使用追加流对象,在下面字符流中会提到


字符流

操作文本文件

Reader Writer / FileReader FileWriter


写文件:

  public static void main(String[] args) throws IOException {
        File file = new File("./text3.txt"); //不写./默认本地路径下
        file.createNewFile();

        //读操作
        Reader reader = new FileReader(file);

        while(true){
            int ch = reader.read(); //返回值也是int  当为-1时表示文件读完
            if(ch == -1){
                break;
            }
            System.out.print((char)ch);
        }

read的返回值也是int,当为-1时表示读完,读的是字符/字符数组/字符串


写操作

  //写操作
        File file1 = new File("./text4.txt");
        file1.createNewFile();
        Writer writer = new FileWriter(file1);
        String s = "你说你爱过的人都已经离去";
        //这样的写操作 大多是将内容写入缓冲区中 执行完后 可能还在缓冲区中 并没有写入硬盘
        //此时可以使用flush // close操作--->会触发缓冲区刷新 来刷新缓冲区中的内容到硬盘
        writer.write(s);
        writer.flush();

写操作后,需要调用flush方法,为很有可能只是写入了缓冲区中,并还没有写入到硬盘上,故内容无法显示,使用flush可以将缓冲区中的内容刷新到硬盘上


追加写操作

 public static void main(String[] args) throws IOException {
        File file = new File("./aaa/text.txt");
        file.createNewFile();

        //字符流 --- 文本文件
        //1.追加写操作 ----- FileWriter 追加流对象
        FileWriter fileWriter = new FileWriter(file,true);
        String src = " 我借来寄托";
        fileWriter.write(src);
        fileWriter.flush();

        //2.追加写操作 ×
        //Writer writer = new FileWriter(file);
        //并没有实现追加功能
        //writer.append(null);
        //writer.flush();
    }

将构造方法时第二个参数boolean append设置为true,即可在原本内容后面进行追加写


拷贝文件
 public static void main(String[] args) throws IOException {
        //复制文本文件到指定目录
        //语法点:try with resources  此时不需要flush操作了
        //此时这种写法虽然没有写close 但在try语句块执行完后 会自动执行close
        //条件:放在try语句块中的对象必须要实现Closeable接口 ---- 提供的方法就是close
        try( Reader reader = new FileReader("./text.txt");
             Writer writer = new FileWriter("C:/Users/depth/Desktop/text.txt")){
            while(true){
                int ch = reader.read();
                if(ch == -1){
                    break;
                }
                //换转换成字符
                writer.write(ch);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

注意这里的语法点:try with resources

当将流对象放在try代码块中,这样当try中的代码块执行完后,会自动执行close方法,而close方法中就会刷新缓冲区,这样就可以不用调用flush方法了

注意,前提条件:try代码块中的对象必须实现Closeable接口,其接口提供的方法就是close


删除指定文件夹
public class deleteFile {
    private static Scanner sc = new Scanner(System.in);

    //循环扫描文件 / 文件夹
    public static void scanDir(File root, String fileName){
        File[] fileLists = root.listFiles();
        if(root == null){
            return;
        }

        for(File file : fileLists){
            if(file.isFile()){
                continue;
            }else if(file.isDirectory()){
                File[] files = file.listFiles();
                for(File f : files){
                    if(f.getName().contains(fileName)){
                        System.out.println("是否确定删除此文件夹:"+f.getAbsolutePath());
                        System.out.println("Y:删除  其他:取消");
                        String option = sc.next();
                        if(option.equals("Y")){
                            deleteFolder(f);
                            System.out.println("删除完成");
                        }else{
                            System.out.println("取消删除");
                        }

                    }
                }
                scanDir(file,fileName);
            }
        }
    }
    
    //循环遍历删除文件夹及子内容
    public static void deleteFolder(File file){
        File[] files = file.listFiles();
        for(File f : files){
            if(f.isFile()){
                f.delete();
            }else{
                deleteFolder(f);
            }
        }
        //只有文件夹为空时 才可以使用delete方法删除文件夹对象
        file.delete();
    }

    public static void main(String[] args) {
        //指定删除文件 / 文件夹
        while(true){
            System.out.println("请输入删除文件的路径");
            String dir = sc.next();

            File file = new File(dir);
            if(!file.isDirectory()){
                System.out.println("此路径否目录 请重新输入");
            }

            System.out.println("请输入需要删除的文件名");
            String fileName = sc.next();
            scanDir(file,fileName);
        }
    }
}

值得注意的是删除文件夹操作:循环遍历删除,如果有子文件夹,先把子文件夹下的文件全部删除后,再删除子文件夹,因为delete方法删除文件夹只能删除空的文件夹


close:

每一个pcb(程序控制块)下都有一个文件操作描述符,当我们进行IO操作时,就会在里面申请位置,将相关信息放到里面


是否需要必须执行close操作?

如果是执行一个程序,里面的文件操作对象自始至终地都要使用,那么此时不执行close方法

也没什么,因为随着程序的关闭,pcb随之销毁,文件操作描述符也会随之销毁


但不怕一万 就怕万一

如果我们一直都不执行close方法,有小伙也会说,咱不是还有GC垃圾回收,但可能回收的不及时,当文件操作描述符被沾满后(是个数组,不会自动扩容,有长度上限),此时打开文件就失败了


那怎么样才能保证能执行到close方法呢?----- try with resources

将能执行close方法的对象放到try代码块中,虽然这里没有显示的执行close方法,但会自动执行的注意放进去的对象必须得实现Closeable接口才会被自动释放

  • 32
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值