[JAVAee]文件操作-IO

news2024/9/28 5:24:51

本文章讲述了通过java对文件进行IO操作

IO:input/output,输入/输出. 

建议配合文章末尾实例食用

目录

文件

文件的管理

文件的路径

文件的分类

文件系统的操作

File类的构造方法

File的常用方法

文件内容的读写

FileInputStream读取文件

构造方法

常用方法

Scanner读取

FileOutputStream写入文件

PrintfWriter写入

关于close()方法

文件操作示例

根据文件名搜索并删除文件

文件的复制

根据文件内容或文件名搜索


文件

针对硬盘来说,会将存储的数据分成一个一个独立的单位进行保存,这个独立的单位就被抽象的称为"文件".

我们平时的文件都是存储在硬盘当中的.

文件的管理

随着存储的数据增多,对于这些数据也会进行一定的管理.

对于文件,我们会进行层级管理,也就是数据结构中的树形结构.就这样,出现了一种管理文件的特殊文件:目录(directory)也就是俗称的文件夹.

文件的路径

路径(path)是一个文件在系统中的具体位置.

从树形结构来看,就是由上到下的从一个根节点开始描述到目标文件.

路径的表示:从盘符开始,用"\"或"/"分割开(在Windows中一般都从"此电脑"开始,表示的时候可以将其忽略)

路径根据"基准目录"的不同,又可以分为:

  • 绝对路径:从盘符开始往下遍历直到目标文件,所得到的路径
  • 相对路径:从指定的目录开始往下遍历直到目标文件,所得到的路径

C:\Program Files\Java\jdk1.8.0_192(绝对目录)

\Java\jdk1.8.0_192(相对目录)

在windows系统上,一个文件的路径是绝对唯一的,可以说文件与路径一一对应的.

文件的分类

根据所保存的数据的不同,文件可以被分为:

二进制文件:按照标志格式保存的没被字符集编码过的文件

文本文件:存储被字符集编码过的文本

文件系统的操作

 在JAVA的标准库当中,提供了File这个类.

此处的File实例化出的对象是硬盘上一个文件或目录的抽象表示.

File类的构造方法

构造方法中的路径指定的文件可以是存在的,也可以是不存在的.

File(File parent, String child)

通过父亲抽象路径名与子抽象路径名创建一个File实例

File(String pathname)

通过转换传输的路径名字符串转化成为抽象路径名来创建File实例

File(String parent, String child)

从父路径名字符串和子路径名字符串创建新的 File实例。

File(URI uri)

通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。

File的常用方法

这些方法的作用都能很清楚的明白,就不再一一演示了.

修饰符及返回
值类型
方法说明
StringgetParent()返回 File 对象的父目录文件路径
StringgetName()返回 FIle 对象的纯文件名称
StringgetPath()返回 File 对象的文件路径
StringgetAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()判断 File 对象代表的文件是否是一个目录
booleanisFile()判断 File 对象代表的文件是否是一个普通文件
booleancreateNewFile()根据 File 对象,自动创建一个空文件。成功创建后返
回 true
booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()根据 File 对象,标注文件将被删除,删除动作会到
JVM 运行结束时才会进行
String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()返回 File 对象代表的目录下的所有文件,以 File 对象
表示
booleanmkdir()创建 File 对象代表的目录
booleanmkdirs()创建 File 对象代表的目录,如果必要,会创建中间目
booleanrenameTo(File
dest)
进行文件改名,也可以视为我们平时的剪切、粘贴操
booleancanRead()判断用户是否对文件有可读权限
booleancanWrite()判断用户是否对文件有可写权限

如果放入的是绝对路径 

public static void main(String[] args) throws IOException {
        File file = new File("D:\\tools\\TMP");
        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());
    }

 放入的是相对路径.

当调用打印绝对路径与相对路径的时候会根据当前所在的工作目录创建.

这时候,文件是并不存在的.调用createNewFile()才会创建新的文件.

File file = new File(".\\TMP");

文件内容的读写

针对文件内容的操作,会使用到"流"来操作.

流,从字面意思上可以看作为"水流",是可以随心所读的读写的.对于读取数据,可以一次读取1个字节,5个字节,10个字节也可以一次性读完100个字节.相反,对于写入数据来说,也是一样的.这些数据不会被限制一次只能读取一定量或被捆绑在一起.

因此,就把读写文件相关的对象,成为"流对象".

在java标准库的流对象,从类型上可以分成两大类:

  • 字节流对象:InputStream,OutputStream...(可以读取文本文件与二进制文件)
  • 字符流对象:Reader,Writer...(只能读取文本文件)

在此处的输入与输出,是以CPU为基准的:

Input是从CPU向硬盘输入,达到读取文件的效果.

Output是从CPU向硬盘输出,达到写入文件的效果. 

FileInputStream读取文件

上面介绍的字节流对象的InputStream只是一个抽象类,对于文件的IO来说.使用其中一个实现类FileInputStream就可以了

构造方法

方法说明
FileInputStream(File file)利用 File 构造文件输入流
FileInputStream(String name)利用文件路径构造文件输入流
//构造方法1
File file = new File("D:/tools/TMP/book.txt");
FileInputStream inputStream = new FileInputStream(file);
//构造方法2        
FileInputStream inputStream1 = new FileInputStream("D:/tools/TMP/book.txt");

常用方法

修饰符及
返回值类
方法说明
intread()读取一个字节的数据,返回 -1 代表已经完全读完了
intread(byte[] b)最多读取 b.length 字节的数据到 b 中,返回实际读到的数
量;-1 代表以及读完了
intread(byte[] b,
int off, int len)
最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返
回实际读到的数量;-1 代表以及读完了
voidclose()关闭字节流

无参数read 

        while(true){
            int n = inputStream.read();
            if(n == -1){
                break;
            }
            System.out.printf("%c",n);//%c是字符型格式符,以字符为单位进行输出.直接输出会得到的是ASCII码
        }
        inputStream.close();//释放资源

byte[]参数read(更推荐使用此方法)

带有数组参数的read能够极大的减少对文件的IO次数,减少了发生异常的可能.

        byte[] buf = new byte[1024];//数组的长度为一次读取的字节数
        while(true){                //数组的长度不能一次读完字节,下一次的读取就会覆盖上一次的数据
            int len;
            len = inputStream.read(buf);
            if(len == -1){
                break;
            }
            for(int i = 0; i < len; i++){
                System.out.println(buf[i]);
            }
        }
        inputStream.close();//释放资源

Scanner读取

将FileInputStream套上一个Scanner更方便的操作

构造方法说明
Scanner(InputStream is, String charset)使用 charset 字符集进行 is 的扫描读取
Scanner scanner = new Scanner(inputStream,"UTF_8");
        while(scanner.hasNext()){
            String s = scanner.next();
            System.out.println(s);
        }
        scanner.close();

FileOutputStream写入文件

构造方法与FileInputStream是基本相同的.

返回
值类
方法签名说明
voidwrite(int b)写入要给字节的数据
voidwrite(byte[] b)将 b 这个字符数组中的数据全部写入 os 中
int

write(byte[] b,int off,

int len)

将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
voidclose()关闭字节流
voidflush()

刷新此输出流并强制任何缓冲的输出字节被写出

  • 关于flush方法,计算机为了减少I/O的次数.在写入数据的时候,先会把数据放入到缓冲区当中.如果数据特别小的,可能还在缓冲区中.未能及时的放到文件当中,其他流可能就会读取不到.
        FileOutputStream outputStream = new FileOutputStream("D:/tools/TMP/book.txt");
        outputStream.write('H');//单个字符

        byte[] arr = {(byte) 'E',(byte) 'L'};//byte[]
        outputStream.write(arr);

        String s = "LO";
        byte[] arr2 = s.getBytes("UTF-8");//将字符串转换成"UTF-8"字符集的字符放入byte[]
        outputStream.write(arr2);
        outputStream.flush();//刷新缓冲区
        outputStream.close();

写入后,会覆盖原有的数据.

PrintfWriter写入

FileOutputStream outputStream = new FileOutputStream("D:/tools/TMP/book.txt");
PrintWriter writer = new PrintWriter(outputStream);
writer.println("hello");
writer.flush();
writer.close();
outputStream.close();

关于close()方法

前面介绍了进程,关于进程会用PCB来进行描述

而PCB里又包括了:

  • pid
  • 内存指针
  • 文件描述符

对于close,我们释放的主要是文件描述符.其记载了在此进程中,打开了什么文件,关闭了什么文件或正在使用什么文件等.就像一个数组一样,每进行一个操作会占上一个下标,但表的长度有限,可能会被完全占满.一旦占满了不进行释放,再继续打开文件就会发生错误,可能造成文件资源泄露的问题.

除了直接的使用close方法释放资源,还可以使用相应的带有资源的try方法.

这样就不怕忘记使用close方法了

try(FileInputStream inputStream1 = new FileInputStream("D:/tools/TMP/book.txt")){
            byte[] buf = new byte[1024];
            while(true){
                int len;
                len = inputStream.read(buf);
                if(len == -1){
                    break;
                }
                for(int i = 0; i < len; i++){
                    System.out.println(buf[i]);
                }
            }
        }

文件操作示例

根据文件名搜索并删除文件

主要思路是:

  • 遍历当前的目录,如果遍历到的文件是一个目录继续递归遍历
  • 如果是一个普通文件,则判断是否为我们要找的文件
    public static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) {
        //输入要搜索的目录
        //判断目录是否存在
        //输入要删除的文件名
        //遍历目录,搜索文件是否存在
        System.out.println("请输入要搜素的根目录的路径");
        String dirName = scanner.next();

        File dir = new File(dirName);//创建目录实例

        if(!dir.isDirectory()){//判断是否为目录
            System.out.println("输入的路径并非根目录,或根目录不存在");
            return;
        }

        System.out.println("输入要删除的文件的关键字");
        String keyName = scanner.next();

        scanner(dir,keyName);
    }
    public static void scanner(File dir,String keyName){
        File[] files = dir.listFiles();//此方法,将dir当中的文件存储到File[]中
        if(files == null){
            return;//证明这个目录下没有东西了
        }
        //如果目录下还有东西,就将他遍历一遍
        for (File f: files) {
            if(f.isDirectory()){
                //如果还是目录,递归遍历里面的文件
                scanner(f,keyName);
            }else{
                //如果是普通文件,判断是否带有关键字
                if(f.getName().contains(keyName)){
                    //如果带有关键字
                    System.out.println("输入\"YES\"来确认是否要删除: " + f.getAbsolutePath());
                    System.out.println("输入任意其他取消删除");
                    String s = scanner.next();
                    if(s.equals("YES")){
                        System.out.println(f.delete());
                    }else{
                        System.out.println("取消");
                    }
                }
            }
        }
    }

 

文件的复制

主要思路:

  • 判断被复制的文件在不在或者是否为一个普通文件
  • 判断要去的路径存不存在被复制的文件
  • 从被复制的文件进行读操作,再进行写操作写入到目标处
    public static void main(String[] args) {
        //判断被复制的文件在不在或者是否为一个普通文件
        //判断要去的路径存不存在被复制的文件
        //从被复制的文件进行读操作,再进行写操作写入到目标处
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入要复制的文件的路径");
        String source = scanner.next();//要复制的文件
        File sourFile = new File(source);
        if(!sourFile.isFile()){
            //判断是否为一个普通文件,同时也判断了其是否存在
            System.out.println("路径错误,目标无法复制");
            return;
        }
        System.out.println("输入要复制到的路径");
        String dir = scanner.next();
        File dirFile = new File(dir);//要复制去的路径
        if(dirFile.isFile()){
            //如果已经有了文件,则不进行复制
            System.out.println("文件已存在或路径错误");
            return;
        }
        //进行读写操作
        //使用带资源的try,最后会自动释放资源
        try(InputStream inputStream = new FileInputStream(sourFile); OutputStream outputStream = new FileOutputStream(dirFile)) {
            byte[] buf = new byte[1024];
            while(true){
                int len = inputStream.read(buf);
                if(len == -1){
                    System.out.println("复制完毕");
                    break;
                }
                outputStream.write(buf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

根据文件内容或文件名搜索(简单版)

    //遍历目录,读取普通文件的内容与关键字进行匹配
    //如果是目录则递归遍历
    public static List<File> ret = new ArrayList<>();
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入要搜索的目录路径");
        String s = scanner.next();
        File sFile = new File(s);
        if(!sFile.isDirectory()){
            System.out.println("输入的路径有误");
            return;
        }
        System.out.println("输入关键字");
        String keyName = scanner.next();
        scan(sFile,keyName);
        System.out.println("相关搜索的文件有");
        for (File f:ret) {
            System.out.println(f.getAbsolutePath());
        }
    }
    public static void scan(File root,String keyName){
        File[] files = root.listFiles();//得到当前目录的所有文件
        if(files == null){
            //递归结束的条件
            return;
        }
        for (File f:files) {
            if(f.isDirectory()){
                //如果是目录
                //继续递归
                scan(f,keyName);
            }else{
                //如果是普通文件
                //判断文件名是否存在关键字
                //判断内容是否存在关键字
                //如果满足其一,则放到列表中
                if(isContainOnName(f,keyName) || isContainOnContent(f,keyName)){
                    ret.add(f);
                }
            }
        }
    }
    public static boolean isContainOnName(File file,String keyName){
        return file.getName().contains(keyName);
    }
    public static boolean isContainOnContent(File file,String keyName){
        //进行读操作
        //组成一个字符串,判断keyName是否存在字符串中
        //当然这种方法有点蠢,性能非常差.不要用于大文件当中
        StringBuffer buffer = new StringBuffer();
        try(InputStream inputStream = new FileInputStream(file);Scanner scan = new Scanner(inputStream,"UTF-8")){
           while(scan.hasNext()){
               buffer.append(scan.next());
           }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.indexOf(keyName) != -1;//StringBuffer没有contains可以用indexOf,如果返回值为-1代表无子串
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/808918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VLAN原理(Virtual LAN 虚拟局域网)

VLAN&#xff08;Virtual LAN 虚拟局域网&#xff09; 1、广播/广播域 2、广播的危害&#xff1a;增加网络/终端负担&#xff0c;传播病毒&#xff0c; 3、如何控制广播&#xff1f;&#xff1f; ​ 控制广播隔离广播域 ​ 路由器物理隔离广播 ​ 路由器隔离广播缺点&…

BLE配对和绑定

参考&#xff1a;一篇文章带你解读蓝牙配对绑定 参考&#xff1a;BLE安全之SM剖析(1) 参考&#xff1a;BLE安全之SM剖析&#xff08;2&#xff09; 参考&#xff1a;BLE安全之SM剖析(3) 目录 前言基本概念解读Paring(配对)Bonding(绑定&#xff09;STK短期秘钥、LTK长期秘钥等 …

通过案例实战详解elasticsearch自定义打分function_score的使用

前言 elasticsearch给我们提供了很强大的搜索功能&#xff0c;但是有时候仅仅只用相关度打分是不够的&#xff0c;所以elasticsearch给我们提供了自定义打分函数function_score&#xff0c;本文结合简单案例详解function_score的使用方法&#xff0c;关于function-score-query…

const对象不能调用其他非const成员函数,const成员函数不能调用其他非const成员,

在C语言中我们知道const关键字修饰的变量具有常量属性&#xff0c;简称常变量。即修饰后的变量不能再次修改&#xff0c;而C中是兼容C语言的&#xff0c;同样具备该特性&#xff0c;但C引入了引用&#xff08;&&#xff09;所以const的用法就更多了。 我们知道引用的对象必…

rust 闭包函数

函数有自己的类型&#xff0c;可以像使用基础类型一样使用函数&#xff0c;包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数&#xff0c;也有自己的类型定义。不过&#xff0c;函数实际上是指针类型&#xff0c;在 rust 所有权中属于借用的关…

主从搭建失败的原因

1、Slave_IO_Running是connecting&#xff0c;Slave_SQL_Running是yes 是因为从机使用配置的主机信息没有登陆到主机里面&#xff01;修改(从机里面) 2、Slave_IO_Running是yes&#xff0c;Slave_SQL_Running是no 原因是主机和从机里的数据不一致&#xff1a; 导致&#xff…

轮趣科技教育版ros小车键盘控制运动

我之前买的ros小车是单独买的底板&#xff0c;以为随便一个树莓派就可以&#xff0c;因为我以前有一个树莓派3B&#xff0c;后来买了单独的小车之后&#xff0c;发现只能使用树莓派4B&#xff0c;然后又单独买了一个树莓派4B&#xff0c;给装上镜像&#xff0c;安装ros-melodic…

容斥原理 训练笔记

​ 容斥原理 设S是一个有限集&#xff0c;A_1,A_2…A_n是S的n个子集&#xff0c;则 ∣ S − ⋃ i 1 n A i ∣ ∑ i 0 n ( − 1 ) i ∑ 1 ≤ j 1 < j 2 . . . < j i ≤ n ∣ ⋂ k 1 i A j k ∣ |S-\bigcup_{i1}^{n}A_i|\sum_{i0}^{n}(-1)^i\sum_{1\leq j_1< j_2.…

简单说说SAP系统中BASIS这个Package

1. 简介 BASIS是SAP系统中非常基础的一个包&#xff0c;属于SAP_BASIS这个模块&#xff0c;这个模块其实也代表着SAP Netweaver的版本&#xff0c;通常而言&#xff0c;SAP_BASIS的版本越高&#xff0c;其所支持的功能也越丰富&#xff0c;例如功能更丰富的ABAP语法&#xff0…

UE4 unlua学习笔记

将这三个插件放入Plugins内并重新编译 创建一个BlueprintLibrary&#xff0c;声明一个全局函数 在这里声明路径 点击Create Lua Template 在Content的Script即可生成对应的lua文件打开它&#xff01; 显示以上lua代码 打印Hello Unlua 创建该UI&#xff0c;就会在创建UI的Con…

数值分析第五章节 用Python实现解线性方程组的直接解法

参考书籍&#xff1a;数值分析 第五版 李庆杨 王能超 易大义编 第5章 解线性方程组的直接解法 文章声明&#xff1a;如有发现错误&#xff0c;欢迎批评指正 文章目录 引言与预备知识高斯消去法列主元消去法 矩阵三角分解法杜利特尔分解法平方根法 向量和矩阵的范数误差分析 引言…

剑指offer42.连续子数组的最大和

这道题挺简单的&#xff0c;看完题脑子里出现的想法就是用一个sum来把数组从前往后加&#xff0c;如果sum小于0&#xff0c;那么对于和来说是会减小的&#xff0c;所以这个时候直接把sum归零&#xff0c;然后从这个位置再往后加&#xff0c;用一个max_sum来记录sum的最大值&…

全面适配 | 走近openGauss数据库+鲲鹏欧拉操作系统

引入 全面适配 | openEuler操作系统 openGauss数据库 开篇 1、openEuler欧拉操作系统 百度百科&#xff1a;openEuler是覆盖全场景的创新平台&#xff0c;在引领内核创新&#xff0c;夯实云化基座的基础上&#xff0c;面向计算架构互联总线、存储介质发展新趋势&#xff0c;…

【LeetCode】剑指 Offer Ⅱ 第1章:整数(5道题) -- Java Version

题库链接&#xff1a;https://leetcode.cn/problem-list/e8X3pBZi/ 题目解决方案剑指 Offer II 001. 整数除法快速除 ⭐剑指 Offer II 002. 二进制加法模拟&#xff1a;StringBuilder ⭐剑指 Offer II 003. 前 n 个数字二进制中 1 的个数动规&#xff1a;res[i] res[i & (…

路由的配置

1、在router中设置路由导航跳转函数,在index.js文件中写这句话&#xff1a; 1.1 只要发生跳转, 就会调用这个函数&#xff1a; 1.2 导航的声明函数 2、访问系统访问控制系统如何形成 3、来一个导航守卫的案例&#xff1a;看看导航守卫的案例&#xff0c;写一个Main.Vue 和login…

【微软知识】微软相关技术知识分享

微软技术领域 一、微软操作系统&#xff1a; 微软的操作系统主要是 Windows 系列&#xff0c;包括 Windows 10、Windows Server 等。了解 Windows 操作系统的基本使用、配置和故障排除是非常重要的。微软操作系统&#xff08;Microsoft System&#xff09;是美国微软开发的Wi…

中文LLaMA模型和指令精调的Alpaca大模型:中文数据进行二次预训练,进一步提升了中文基础语义理解能力

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

Pytorch个人学习记录总结 10

目录 优化器 优化器 官方文档地址&#xff1a;torch.optimhttps://pytorch.org/docs/stable/optim.html Debug过程中查看的grad所在的位置&#xff1a; model --> Protected Atributes --> _modules --> ‘model’ --> Protected Atributes --> _modules -…

Linux学成之路(基础篇0(二十三)MySQL服务(主从MySQL服务和读写分离——补充)

目录 一、MySQL Replication概述 优点 异步复制&#xff08;Asynchronous repication&#xff09; 全同步复制&#xff08;Fully synchronous replication&#xff09; 半同步复制&#xff08;Semisynchronous replication&#xff09; 三、MySQL支持的复制 四、部署主从…

解决AttributeError: ‘DataParallel‘ object has no attribute ‘xxxx_fc1‘

问题描述 训练模型时&#xff0c;分阶段训练&#xff0c;第二阶段加载第一阶段训练好的模型的参数&#xff0c;接着训练 第一阶段训练&#xff0c;含有代码 if (train_on_gpu):if torch.cuda.device_count() > 1:net nn.DataParallel(net)net net.to(device)第二阶段训练…