JaveEE初阶--文件操作和IO

在这里插入图片描述

一:基本概念

针对硬盘这种持久化存储的I/O设备,当我们想要进行数据保存时,往往不是保存成一个整体,而是独立成一个个的单位进行保存.这里所说的"单位"其实就是文件.

文件,是存储在硬盘上的!

Q : 硬盘和内存的区别 :

A :

  1. 内存存储空间小,硬盘存储空间大;
  2. 内存访问速度快,硬盘访问速度慢;
  3. 内存成本较高,硬盘比较便宜;
  4. 内存掉电数据丢失,硬盘掉电数据还在.

Q : 文件在计算机中的组织形式 ?

A : 文件在计算机中是按照树形结构组织的 .
在这里插入图片描述

Q : 如何在文件系统中定义唯一的一个文件呢 ?

A : 答案是"文件路径".

路径的分类 :

  • 绝对路径 : 树中的每个结点都可以被一条从根开始,一直到达终点的路径所描述,而这种描述方式就被称为文件的绝对路径(absolute path) .以盘符开头的路径称为绝对路径 .
  • 相对路径 : 除了可以从根开始进行路径的描述,我们可以从任意结点出发,进行路径的描述,而这种描述方式就被称为相对路径(relative path),相对于当前所在结点的一条路径 .以.或者…开头的路径称为相对路径 .

注意 : 目录与目录之间可以使用 / 或者 \ 进行分割 .

Q : 普通文件的分类?

A :

在这里插入图片描述

了解普通文件的分类 , 有助于我们后续进行文件的操作 .

Q : 其他注意事项 ?

A :

  1. 文件是被操作系统管理的 , 操作系统内核中有一个专门的模块 , 文件系统 , Java针对文件系统/文件进行了一系列的封装 …
  2. 文件由于被操作系统进行了管理,所以根据不同的用户,会赋予用户不同的对待该文件的权限,一般地可以认为有可读、可写、可执行权限。
  3. Windows 操作系统上 , 还有一类文件比较特殊 , 就是"快捷方式" (shortcut) , 这种文件只是对真实文件的一种引用而已 .
  4. 很多操作系统为了实现接口的统一性 , 将所有的 I/O 设备都抽象成了文件的概念 , 使用这一理念最为知名的就是 Unix、Linux 操作系统-----万物皆文件 .

二:文件的操作

Java 中通过 java.io.File 类来对一个文件 (包括目录) 进行抽象的描述.

对文件的操作包括 :

  • 打开文件 ;
  • 关闭文件 ;
  • 读文件 ;
  • 写文件 ;

2.1File

2.1.1构造方法

在这里插入图片描述
在这里插入图片描述

2.1.2 常用方法

2.1.2.1 常用方法介绍

在这里插入图片描述

2.1.2.2代码示例
import java.io.File;
import java.io.IOException;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //File file = new File("d:/test.txt");
        File file = new File("./test.txt");
        System.out.println(file.getParent());//父目录文件路径
        System.out.println(file.getName());//纯文件名称
        System.out.println(file.getPath());//文件路径
        System.out.println(file.getAbsolutePath());//绝对路径
        System.out.println(file.getCanonicalPath());//修饰过的绝对路径
    }
}

在这里插入图片描述

getCanonicalPath():此路径方法返回绝对唯一的标准规范路径名。此方法首先将此路径名转换为绝对形式,就像调用getAbsolutePath方法一样,然后以系统相关的方式将其映射到其唯一路径上。
也就是说如果路径中包含“.”或“…”等当前路径及上层路径表示法,则会从路径名中删除“.”和“…”使用真实路径代替。

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

public class Demo2 {
    public static void main(String[] args) throws IOException {
        File file = new File("test1.txt");
        System.out.println(file.exists());//是否存在
        System.out.println(file.isDirectory()); //是否是一个目录
        System.out.println(file.isFile());//是否是一个文件
        System.out.println("=====================");
        //创建文件
        file.createNewFile();
        System.out.println(file.exists());
        System.out.println(file.isDirectory()); 
        System.out.println(file.isFile());
    }
}

在这里插入图片描述

import java.io.File;

public class Demo3 {
    public static void main(String[] args) {
        File file = new File("test1.txt");
        System.out.println(file.exists());
        file.delete();
        System.out.println(file.exists());
    }
}

在这里插入图片描述

import java.io.File;

public class Demo4 {
    public static void main(String[] args) throws InterruptedException {
        File file = new File("test/demo1/1.1");
        System.out.println(file.exists());
        System.out.println(file.isDirectory());
        System.out.println("=============");
        file.mkdirs(); //创建目录
        System.out.println(file.exists());
        System.out.println(file.isDirectory());
    }
}

在这里插入图片描述

import java.io.File;

public class Demo5 {
    //文件重命名
    public static void main(String[] args) {
        File file1 = new File("xiaoqin.txt");
        File file2 = new File("xiaoxiaoqin.txt");
        file1.renameTo(file2);
    }
}

在这里插入图片描述

2.2 文件内容的读写—数据流

2.2.1 综述

在Java中关于文件读写,提供了一些类.
  • 第一组 : InputStream OutputStream
  • 第二组 : Reader Writer

Q : 流的分类 ?

A :

  • 字节流 : 以字节为单位的流 , 用来操作二进制文件
  • 字符流 : 以字符为单位的流 , 用来操作文本文件

2.2.2 InputStream

2.2.2.1 方法介绍

在这里插入图片描述

注意 : InputStream 不能直接实例化 , 而是需要用到子类FileInputStream , 用于读文件 .

2.2.2.2 代码示例
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class Demo6 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = null;

        try{
            //1.打开文件
            inputStream = new FileInputStream("xiaoxiaoqin.txt");

/**            2.读取文件---方法一
 *             while (true) {
 *                 int b = inputStream.read();
 *                 if(b == -1){
 *                     //文件读完了
 *                     break;
 *                 }
 *                 System.out.println(b);
 *             }
 */

/**
 *             2.读取文件---方法二
 *         byte[] b = new byte[1024];
 *         int len = inputStream.read(b);
 *
 *             for (int i = 0; i < len; i++) {
 *                 System.out.println(b[i]);
 *             }
 */

//            2.读取文件---方法三
            byte[] b = new byte[1024];
            int len = inputStream.read(b);

            String s = new String(b,0,len,"utf-8");
            System.out.println(s);

        } catch (IOException e){
            e.printStackTrace();
        } finally {
            inputStream.close();
        }

    }
}

方法一二运行结果 :

在这里插入图片描述

方法三运行结果 :

在这里插入图片描述

2.2.2.3代码分析

在这里插入图片描述

在这里插入图片描述

注意 :

  • 文件描述符表可以通过配置项 , 手动调整这里的大小 . 手动调整 , 而不是自动扩容 !
  • 其次 , 如果打开后忘记关闭文件 , 其危害是非常大的 , 因为文件资源泄露是一个逐渐的过程 , 不是立即就泄露完 , 这就好像一个定时炸弹 , 当服务器程序需要7*24 h 运行时 , 指不定什么时候程序就会奔溃 !

在这里插入图片描述
因此 , 可以通过字符流解决上述问题 , 代码示例如下 :

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class Demo7 {
    public static void main(String[] args) throws IOException {
        //使用字符流读取文件
        Reader reader = new FileReader("xiaoxiaoqin.txt");
        char[] buffer = new char[1024];
        int len = reader.read(buffer);
        for (int i = 0; i < len; i++) {
            System.out.print(buffer[i]);
        }
        reader.close();
    }
}

在这里插入图片描述

对于文本文件 , 还有更简单的写法 , 就是借助Scanner .

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

public class Demo8 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("xiaoxiaoqin.txt");
        Scanner scanner = new Scanner(inputStream);
        String s = scanner.next(); //读一行
        System.out.println(s);     //直接打印
        inputStream.close();
    }
}

在这里插入图片描述

还有一种更加简单的写法 , 无需进行try-catch-finally , 代码如下 :

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

public class Demo9 {
    public static void main(String[] args) {
        try(InputStream inputStream = new FileInputStream("xiaoxiaoqin.txt")){
            byte[] b = new byte[1024];
            int len = inputStream.read(b);
            for (int i = 0; i < len; i++) {
                System.out.println(b[i]);
            }
            } catch (IOException e) {
                e.printStackTrace();
        }
    }
}

在这里插入图片描述

2.2.3OutputStream

2.2.3.1方法介绍

在这里插入图片描述

2.2.3.2代码示例
2.2.3.2.1使用字节流
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Demo10 {
    public static void main(String[] args) {
        try(OutputStream outputStream = new FileOutputStream("xiaoxiaoqin.txt")){
            outputStream.write('a');
            outputStream.write('p');
            outputStream.write('p');
            outputStream.write('l');
            outputStream.write('e');
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

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

public class Demo10 {
    public static void main(String[] args) {
        try(OutputStream outputStream = new FileOutputStream("xiaoxiaoqin.txt")){
        String s = "helloworld";
        outputStream.write(s.getBytes());// 可以得到一个字符数组
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

注意 : 每次写 , 都会把旧的内容清空掉 , 重新写入 .

2.2.3.2.2使用字符流
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Demo11 {
    public static void main(String[] args) {
        try(Writer writer = new FileWriter("xiaoxiaoqin.txt")){
            writer.write("helloChina");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

2.2.3.2.3使用PrintWriter类完成输出
import java.io.*;

public class Demo12 {
    public static void main(String[] args) {
     try(OutputStream outputStream = new FileOutputStream("xiaoxiaoqin.txt")){
         PrintWriter printWriter = new PrintWriter(outputStream);
         printWriter.println("zheshiyifenlibiexin");
         printWriter.flush();
     } catch (IOException e) {
         e.printStackTrace();
     }
    }
}

在这里插入图片描述

2.2.3.3程序分析

在这里插入图片描述

三:案例练习

3.1案例一

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

import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport;

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

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

public class Demo13 {
    //实现递归遍历文件,并询问是否要删除
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径:");
        String rootPath = scanner.next();
        File root = new File(rootPath);
        if(!root.exists()){
            System.out.println("路径无效!");
            return;
        }
        System.out.println("请输入要删除的文件名(或其部分):");
        String toDelete = scanner.next();

        //递归查找
        scanDir(root,toDelete);
    }

    private static void scanDir(File rootDir, String toDelete) {
      File[] files = rootDir.listFiles();// 返回的是该目录下的文件和方法
      if(files == null){
          //空目录,直接返回
          return;
      }

        for (File f : files) {
            if(f.isDirectory()){
                scanDir(f,toDelete);
            } else {
                tryDelete(f,toDelete);
            }
        }

    }

    /**
     * 是文件,看文件名匹配吗?
     * @param f
     * @param toDelete
     */
    private static void tryDelete(File f, String toDelete) {

        if(f.getName().contains(toDelete)){
            try{
                System.out.println("是否要删除文件(Y/N):"+f.getCanonicalPath());
                Scanner scanner = new Scanner(System.in);
                String choice = scanner.next();
                if(choice.equals("Y")){
                    f.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

3.2案例二

进行普通文件的复制 .

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

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

/**
 * 进行普通文件的复制
 */
public class Demo14 {
    public static void main(String[] args) {
        //1.找到文件
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要复制的文件路径:");
        String path = scanner.next();
        File file1 = new File(path);
        if(!file1.exists()){
            System.out.println("要复制的文件不存在!");
            return;
        }
        if(!file1.isFile()){
            System.out.println("要复制的不是普通文件!");
            return;
        }
        System.out.println("请输入要复制到的目标路径:");
        String despath = scanner.next();
        File file2 = new File(despath);
        if(file2.exists()){
            System.out.println("要复制的目标已存在!");
            return;
        }

        //2.进行拷贝
    try(InputStream inputStream = new FileInputStream(file1)){
        try(OutputStream outputStream = new FileOutputStream(file2)){
            byte[] buf = new byte[1024];
            while(true){
                int len = inputStream.read(buf);
                if(len == -1){
                    break;
                }
                outputStream.write(buf,0,len);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    }


}



在这里插入图片描述
在这里插入图片描述

程序分析 :

Q : 为什么不全部读取出来,一次性写入呢 ?

A : 其实也可以 !如果说我申请一个G的内存空间 , 比如byte[] buf = new byte[1024 * 1024 * 1024] , 那么缓冲区内容为1G了 , 大概率可以实现1次全部写入 .

Q : 在while操作时 , 不是每次都会从头开始读吗 ?

在这里插入图片描述

注意:buf是buffer(缓冲区)的缩写,通常是一块内存空间,在IO操作时,可以提高程序的执行效率~~

3.3案例三

遍历目录, 看某个输入的词是否在文件名或者文件内容中存在.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import java.util.logging.FileHandler;

/**
 *遍历目录, 看某个输入的词是否在文件名或者文件内容中存在.
 */
public class Demo15 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你要搜索的目录");
        String rootPath = scanner.next();
        File rootFile = new File(rootPath);
        if(!rootFile.exists()){
            System.out.println("要扫描的目录不存在!");
            return;
        }
        if(!rootFile.isDirectory()){
            System.out.println("要扫描的路径不是目录!");
            return;
        }
        System.out.println("请输入要搜索的词:");
        String toFind = scanner.next();

        //递归遍历目录
        scanDir(rootFile,toFind);
    }

    private static void scanDir(File rootFile, String toFind) throws IOException {
       File[] files = rootFile.listFiles();
       if(files == null){
           return;
       }
        for (File f: files) {
            if(f.isDirectory()){
                scanDir(f,toFind);
            } else {
                tryFind(f,toFind);
            }
        }
    }

    //判断toFind是否是文件名或是文件内容的一部分
    private static void tryFind(File f, String toFind) throws IOException {
      if(f.getName().contains(toFind)){
          System.out.println("找到文件名匹配的文件:"+f.getCanonicalPath());
          return;
      }
      try(InputStream inputStream = new FileInputStream(f)){
          //把文件内容整个读取出来
          StringBuilder stringBuilder = new StringBuilder();
          Scanner scanner = new Scanner(inputStream);
          while(scanner.hasNextLine()){
              stringBuilder.append(scanner.nextLine());
          }
          //读取完毕
          if(stringBuilder.indexOf(toFind) >= 0){
              System.out.println("找到文件内容匹配的文件:"+f.getCanonicalPath());
              return;
          }
      }
    }
}

在这里插入图片描述

以上是文件操作部分的全部内容!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值