18、Java 中操作⽂件

目录

  • 一、Java 中操作⽂件
    • 1、 File 常⽤构造⽅法
    • 2、常⽤⽅法
      • 2.1 观察 get 系列的特点和差异
      • 2.2 ⽂件判断与创建
      • 2.3⽂件存在删除/不存在创建
      • 2.4 观察 deleteOnExit
      • 2.5 观察⽬录的创建
      • 2.6 文件重命名
  • 二、⽂件内容的读写 —— 数据流
    • 2.1 InputStream:输⼊流
      • 2.1.1 InputStream 常⽤⽅法
      • 2.1.2 FileInputStream
      • 2.1.3 读取⽂件中的内容
      • 2.1.4 使⽤ Scanner 进⾏数据读取
    • 2.2 OutputStream:输出流
      • 2.2.1 OutputStream 常⽤⽅法
      • 2.2.2 数据写⼊
      • 2.2.3 使⽤ PrintWriter 进⾏写⼊
      • 2.2.4 使⽤ FileWriter 追加数据
  • 三、应用
    • 3.1 示例1
    • 3.2 示例2
    • 3.3 示例3

一、Java 中操作⽂件

Java 中通过 java.io.File 类来对⼀个⽂件(包括⽬录)进⾏抽象的描述
注意:有 File 对象,并不代表真实存在该⽂件。

1、 File 常⽤构造⽅法

18、Java 中操作⽂件_第1张图片

import java.io.File;

public class FileDemo1 {
    public static void main(String[] args) {
     File pFile=new File("d:\\");
     //构造方法1
        File file=new File(pFile,"a.txt");
        System.out.println("文件a路径:"+file.getPath());

        //构造方法2【重点,使用较多】
        File file1=new File("d:\\b.txt");
        System.out.println("文件b的路径:"+file1.getPath());

        //构造方法3
        File file2=new File("d:\\","c.txt");
        System.out.println("文件c的路径:"+file2.getPath());
    }
}

18、Java 中操作⽂件_第2张图片

2、常⽤⽅法

18、Java 中操作⽂件_第3张图片
18、Java 中操作⽂件_第4张图片

2.1 观察 get 系列的特点和差异

getPath() VS getAbsolutePath() VS getCanonicalPath():

import java.io.File;
import java.io.IOException;

public class FileDemo2 {
    public static void main(String[] args) throws IOException {
        File file=new File("../a.text");
        System.out.println("文件名称:"+file.getName());
        System.out.println("文件目录:"+file.getPath());
        System.out.println("文件绝对路径:"+file.getAbsolutePath());
        System.out.println("文件的标准路径:"+file.getCanonicalPath());
    }
}

18、Java 中操作⽂件_第5张图片
● 绝对路径时,三者⼀致。
●相对路径时:
○ getPath() 是相对路径本身;
○ getAbsolutePath() 是项⽬⽬录 + 相对路径本身;
○ getCanonicalPath() 可以解析相对路径,得到正确的路径。

2.2 ⽂件判断与创建

import java.io.File;
import java.io.IOException;

public class FileDemo3 {
    public static void main(String[] args) throws IOException {
        File file=new File("a.txt");
        System.out.println("文件是否存在:"+file.exists());
        System.out.println("是否为文件夹:"+file.isDirectory());
        System.out.println("是否为文件:"+file.isFile());
        System.out.println();
        boolean result=file.createNewFile();//创建文件
        System.out.println("文件创建:"+result);
        System.out.println("文件是否存在:"+file.exists());
        System.out.println("是否为文件夹:"+file.isDirectory());
        System.out.println("是否为文件:"+file.isFile());
    }
}

18、Java 中操作⽂件_第6张图片
结论:如果⽂件或⽂件夹不存在,使⽤ isDirectory 和 isFile 判断都为 false。

正确用法:
18、Java 中操作⽂件_第7张图片

2.3⽂件存在删除/不存在创建

import java.io.File;
import java.io.IOException;

public class FileDemo4 {
    public static void main(String[] args) throws IOException {
        //先得到一个file对象
        File file = new File("a.text");//存在a.txt文件
        //判断file对象是否存在
        if (file.exists()) {
            //如果存在则删除文件
            boolean result = file.delete();
            System.out.println("文件删除:" + result);
        } else {
            //如果不存在则创建文件
          boolean result=file.createNewFile();
            System.out.println("新建文件:"+result);
        }
    }
}

18、Java 中操作⽂件_第8张图片
18、Java 中操作⽂件_第9张图片

2.4 观察 deleteOnExit

import java.io.File;
import java.io.IOException;

public class FileDemo5 {
    public static void main(String[] args) throws IOException, InterruptedException {
        File file=new File("a.txt");
        if (!file.exists()){
            //如果不存在。新建文件
            System.out.println("新建文件:"+file.createNewFile());
        }
        //删除文件
        System.out.println("开始删除文件");
        file.deleteOnExit();
        //file.delete();
        Thread.sleep(5*1000);
    }
}

结论:
1.delete()有返回值,deleteOnExit()没有返回值。
2.deleteOnExit():程序正常运⾏结束,⽂件被删除;但如果是⼈为停止或退出程序,⽂件不会被删除。
3.delete():不管是程序正常运行结束还是人为结束,文件都会被删除。

2.5 观察⽬录的创建

mkdir():只能创建一级文件夹
mkdirs():可以创建多级文件夹

import java.io.File;

public class FileDemo6 {
    public static void main(String[] args) {
        File file=new File("mytest");//不存在
        System.out.println("是否为文件夹:"+file.isDirectory());
        System.out.println("是否为文件:"+file.isFile());
        System.out.println();
        boolean result=file.mkdir();//创建文件夹
        System.out.println("创建文件夹:"+result);
        System.out.println("是否为文件夹:"+file.isDirectory());
        System.out.println("是否为文件:"+file.isFile());
    }
}

18、Java 中操作⽂件_第10张图片
当创建多级目录时,mkdir()无法成功创建,运行结果如下:
18、Java 中操作⽂件_第11张图片
使用**mkdirs()**可以解决这个问题:

import java.io.File;

public class FileDemo6 {
    public static void main(String[] args) {
        File file=new File("mytest/apps");//不存在
        System.out.println("是否为文件夹:"+file.isDirectory());
        System.out.println("是否为文件:"+file.isFile());
        System.out.println();
        boolean result=file.mkdirs();//创建文件夹
        System.out.println("创建文件夹:"+result);
        System.out.println("是否为文件夹:"+file.isDirectory());
        System.out.println("是否为文件:"+file.isFile());
    }
}

18、Java 中操作⽂件_第12张图片
18、Java 中操作⽂件_第13张图片

2.6 文件重命名

import java.io.File;
import java.io.IOException;

public class FileDemo7 {
    public static void main(String[] args) throws IOException {
   //将a.txt->重命名成b.txt
        File file=new File("a.txt");
        File tarFile=new File("b.txt");
        if (!file.exists()){
            //先创建文件
            file.createNewFile();
        }
        //重命名文件
        boolean result=file.renameTo(tarFile);
        System.out.println("重命名结果:"+result);
    }
}

执⾏两次观察结果可知:如果 renameTo 的⽂件不存在,那么可以重命名成功,反之则不成功。

二、⽂件内容的读写 —— 数据流

2.1 InputStream:输⼊流

InputStream 输⼊流是⽤来读取数据的。

2.1.1 InputStream 常⽤⽅法

18、Java 中操作⽂件_第14张图片
InputStream 只是⼀个抽象类,要使⽤还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输⼊设备都可以对应⼀个 InputStream 类,我们现在只关⼼从⽂件中读取,所以使⽤FileInputStream

2.1.2 FileInputStream

构造方法:
18、Java 中操作⽂件_第15张图片

2.1.3 读取⽂件中的内容

读取⽅式1: 一个字符一个字符读取

package io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamDemo1 {
    public static void main(String[] args) {
        //1.创建流对象
        // 这种写法异常处理太繁琐,代码看起来很臃肿
        InputStream inputStream=null;
        try {
            inputStream=new FileInputStream("c.txt");
            //2.读写操作
            while (true){
                int c=inputStream.read();
                if (c==-1) break;//如果流返回-1,说明数据已经读取完毕
                //让程序稍休眠一会儿,可以明显观察到read()方法时一个字符一个字符读取的
                Thread.sleep(300);
                System.out.printf("%c",c);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //3.关闭流
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

代码优化:

package io;
import java.io.FileInputStream;
import java.io.InputStream;

public class InputStreamDemo2 {
    public static void main(String[] args) {
        //1.创建流对象  try-catch-resource(JDK 1.7):不用进行资源的关闭。jdk会帮助我们关闭资源
        try (InputStream inputStream = new FileInputStream("c.txt")) {
            //2.读写操作
            while (true) {
                int c = inputStream.read();
                if (c == -1) break;//如果流返回-1,说明数据已经读取完毕
                //让程序稍休眠一会儿,可以明显观察到read()方法时一个字符一个字符读取的
                Thread.sleep(300);
                System.out.printf("%c", c);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

18、Java 中操作⽂件_第16张图片
读取⽅式2: 一次性读取

package io;
import java.io.FileInputStream;
import java.io.InputStream;
/**
 * 一次性读取
 */
public class InputStreamDemo3 {
    public static void main(String[] args) {
        try (InputStream inputStream = new FileInputStream("c.txt")) {
          byte[] bytes=new byte[1024];
          while (true) {//如果数据超过了byte容量,会读取多次
              int c = inputStream.read(bytes);
              if (c==-1)break;
               Thread.sleep(300);//即使写了休眠也没有用,因为每次最多可以读取1024个字符。
              System.out.println(new String(bytes,"utf-8"));
          }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.1.4 使⽤ Scanner 进⾏数据读取

我们可以使⽤ Scanner 进⾏数据读取,它有⼀个构造⽅法:
在这里插入图片描述

package io;

import java.io.FileInputStream;
import java.util.Scanner;

public class InputStreamDemo4 {
    public static void main(String[] args) {
    try(FileInputStream inputStream=new FileInputStream("c.txt")){
        try(Scanner scanner=new Scanner(inputStream,"utf8")){
        while (scanner.hasNext()){
            System.out.println(scanner.nextLine());
        }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    }
}

2.2 OutputStream:输出流

OutputStream 输出流是进⾏数据写⼊的。

2.2.1 OutputStream 常⽤⽅法

18、Java 中操作⽂件_第17张图片
OutputStream 同样只是⼀个抽象类,要使⽤还需要具体的实现类。我们现在还是只关⼼写⼊⽂件中,所以使⽤ FileOutputStream

2.2.2 数据写⼊

⼀个⼀个字符写⼊:

package io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 *写入,每次写入一个字符
 */
public class OutputStreamDemo1 {
    public static void main(String[] args) throws IOException {
        File file=new File("mytext.txt");
        if (!file.exists()){
            //新建文件
            System.out.println("新建文件:"+file.createNewFile());
        }
        //文件写入操作
        try(OutputStream outputStream=new FileOutputStream(file)){
            outputStream.write('G');
            outputStream.write('r');
            outputStream.write('e');
            outputStream.write('a');
            outputStream.write('t');
            outputStream.flush();//不能忘记!
        }
    }
}

18、Java 中操作⽂件_第18张图片
字节数组批量写⼊:

package io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class OutputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        File file=new File("mytext.txt");
        if (!file.exists()){
            //新建文件
        file.createNewFile();
        }
        //文件写入操作
        try(OutputStream outputStream=new FileOutputStream(file)){
            byte[] bytes=new byte[]{
                    'h','e','l','l','o'
            };
            outputStream.write(bytes);
            outputStream.flush();
        }
    }
}

18、Java 中操作⽂件_第19张图片
写⼊部分数据:
18、Java 中操作⽂件_第20张图片
字符串写⼊:

package io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamDemo3 {
    public static void main(String[] args) throws IOException {
        File file=new File("mytext.txt");
        if (!file.exists()){
            //新建文件
        file.createNewFile();
        }
        //文件写入操作
        try(OutputStream outputStream=new FileOutputStream(file)){
           String msg="hello,word";
            outputStream.write(msg.getBytes());
            outputStream.flush();
        }
    }
}

字符串中⽂写⼊:

package io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class OutputStreamDemo3 {
    public static void main(String[] args) throws IOException {
        File file=new File("mytext.txt");
        if (!file.exists()){
            //新建文件
        file.createNewFile();
        }
        //文件写入操作
        try(OutputStream outputStream=new FileOutputStream(file)){
           String msg="你好";
            //outputStream.write(msg.getBytes("utf-8"));
            outputStream.write(msg.getBytes(StandardCharsets.UTF_8));
            outputStream.flush();
        }
    }
}

2.2.3 使⽤ PrintWriter 进⾏写⼊

除了上述的写⼊⽅式之外,JDK 还提供了⼀个类 PrintWriter 可以很⽅便的实现数据写⼊。PrintWriter 类中提供了我们熟悉的 print/println/printf ⽅法。

package io;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

public class OutputStreamDemo4 {
    public static void main(String[] args) throws IOException {
        File file=new File("mytext.txt");
        if (!file.exists()){
            file.createNewFile();
        }
        try (PrintWriter printWriter=new PrintWriter(file)){
            printWriter.println("这是第一行数据");
            printWriter.println("这是第二行数据");
            printWriter.printf("我叫:%s,今年:%d岁。","张三",18);
            printWriter.flush();
        }
    }
}

18、Java 中操作⽂件_第21张图片
问题:使⽤ PrintWriter 每次都会覆盖掉原来的数据,追加数据就需要使用 FileWriter类。

2.2.4 使⽤ FileWriter 追加数据

package io;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class OutputStreamDemo5 {
    public static void main(String[] args) throws IOException {
        File file=new File("mytext.txt");
        if (!file.exists()){
            file.createNewFile();
        }
        //数据追加
        //第二个参数为:是否追加数据?
        // 默认为false 所以一定要设置第二个参数为true!!!否则追加会无效果
        try (FileWriter fileWriter=new FileWriter(file,true)){
          //  fileWriter.write("我是追加的数据。");
          fileWriter.write("\n我是追加的数据。");//换行追加:\n
          fileWriter.flush();
        }
    }
}

18、Java 中操作⽂件_第22张图片

三、应用

3.1 示例1

扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤户是否要删除该⽂件。

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        Scanner scanner=new Scanner(System.in);
        System.out.print("请输入要扫描的目录(绝对路径/相对路径):");
        String rootDirPath=scanner.next();

        File rootDir=new File(rootDirPath);
        if (!rootDir.isDirectory()){
            System.out.println("您输入的根目录不存在或者不是目录,退出");
            return;
        }
        System.out.println("请输入要找出的文件的名称:");
        String token=scanner.next();

        //因为文件系统时树形结构的,所以我们要使用深度优先递归完成遍历
        List<File> result=new ArrayList<>();
        sanDir(rootDir,token,result);
        System.out.println("共找到了符合条件的文件"+result.size()+"个,它们分别是");
        for (File file:result){
            System.out.println(file.getCanonicalFile()+"请问您是否要删除该文件?y/n");
            String in=scanner.next();
            if (in.toLowerCase().equals("y")){
                file.delete();
            }
        }
    }

    private static void sanDir(File rootDir, String token, List<File> result) {
    File[] files=rootDir.listFiles();
    if (files==null||files.length==0){
        return;
    }
    for (File file:files){
        if (file.isDirectory()){
            sanDir(file,token,result);
        }else {
            if (file.getName().contains(token)){
                result.add(file.getAbsoluteFile());
            }
         }
      }
    }
}

18、Java 中操作⽂件_第23张图片

3.2 示例2

进⾏普通⽂件的复制。

import java.io.*;
import java.util.Scanner;

/**
 * 进行普通文件的复制
 */
public class Demo2 {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要复制的文件(绝对路径/相对路径):");
        String sourcePath=scanner.next();
        File sourceFile=new File(sourcePath);
        if (!sourceFile.exists()){
            System.out.println("文件不存在,请确认路径是否正确");
            return;
        }
        if (!sourceFile.isFile()){
            System.out.println("文件不是普通文件,请确认路径是否正确");
            return;
        }
        System.out.println("请输入要复制到的目标路径(绝对路径/相对路径):");
        String destPath=scanner.next();
        File destFile=new File(destPath);
        if (destFile.exists()){
            if (destFile.isDirectory()){
            System.out.println("⽬标路径已经存在,并且是⼀个⽬录,请确认路径是否正确");
            return;
        }
        if (destFile.isFile()){
            System.out.println("目录路径已经存在,是否进行覆盖?y/n");
            String ans=scanner.next();
            if (!ans.toLowerCase().equals("y")){
                System.out.println("停止复制");
                return;
            }
        }
    }
    try(InputStream is=new FileInputStream(sourceFile)) {
       try(OutputStream os=new FileOutputStream(destFile)){
           byte[] buf=new byte[1024];
           int len;
           while (true){
               len=is.read(buf);
               if (len==-1){
                   break;
               }
               os.write(buf,0,len);
           }
           os.flush();
       }
    } catch (IOException e) {
        e.printStackTrace();
    }
        System.out.println("复制完成");
    }

}

18、Java 中操作⽂件_第24张图片

3.3 示例3

扫描指定⽬录,并找到名称或者内容中包含指定字符的所有普通⽂件(不包含⽬录)。
注意:我们现在的⽅案性能较差,所以尽量不要在太复杂的⽬录下或者⼤⽂件下实验

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 扫描指定⽬录,并找到名称或者内容中包含指定字符的所有普通⽂件(不包含⽬录
 */
public class Demo3 {
    public static void main(String[] args) throws IOException {
        Scanner  scanner=new Scanner(System.in);
        System.out.println("请输入要扫描的根目录(绝对路径/相对路径):");
        String rootDirPath=scanner.next();

        File rootDir=new File(rootDirPath);
        if (!rootDir.isDirectory()){
            System.out.println("您输入的根目录不存在火灾不是目录,退出");
            return;
        }
        System.out.println("请输入要找出的文件名中的字符:");
        String token=scanner.next();

        List<File> result=new ArrayList<>();
        // 因为⽂件系统是树形结构,所以我们使⽤深度优先遍历(递归)完成遍历
        scanDirWithContent(rootDir,token,result);
        System.out.println("共找到了符合条件的文件"+result.size()+"个,它们分别是");
        for (File file:result){
            System.out.println(file.getCanonicalFile());
        }
    }

    private static void scanDirWithContent(File rootDir, String token, List<File> result) {
     File[] files=rootDir.listFiles();
     if (files==null||files.length==0){
         return;
     }
     for(File file:files){
         if (file.isDirectory()){
             scanDirWithContent(file,token,result);
         }else {
             if (isContentContains(file,token)){
                 result.add(file.getAbsoluteFile());
             }
         }
     }
    }

    private static boolean isContentContains(File file, String token) {
   StringBuilder sb=new StringBuilder();
   try(InputStream is=new FileInputStream(file)){
       try(Scanner scanner=new Scanner(is,"UTF-8")){
           while (scanner.hasNextLine()){
               sb.append(scanner.nextLine());
               sb.append("\r\n");
           }
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
   return sb.indexOf(token)!=-1;
    }
}

18、Java 中操作⽂件_第25张图片

你可能感兴趣的:(JavaEE初阶,java,开发语言,java-ee)