[JAVAee]文件操作-IO

本文章讲述了通过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.mfbz.cn/a/51632.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索容器镜像安全管理之道

邓宇星&#xff0c;Rancher 中国软件架构师&#xff0c;7 年云原生领域经验&#xff0c;参与 Rancher 1.x 到 Rancher 2.x 版本迭代变化&#xff0c;目前负责 Rancher for openEuler(RFO)项目开发。 最近 Rancher v2.7.4 发布了&#xff0c;作为一个安全更新版本&#xff0c;也…

【bar堆叠图形绘制】

绘制条形图示例 在数据可视化中&#xff0c;条形图是一种常用的图表类型&#xff0c;用于比较不同类别的数据值。Python的matplotlib库为我们提供了方便易用的功能来绘制条形图。 1. 基本条形图 首先&#xff0c;我们展示如何绘制基本的条形图。假设我们有一个包含十个类别的…

ElasticSearch 7.x

前言 elastic表示可伸缩&#xff0c;search表示查询。所以es的核心即为查询。通常情况下&#xff0c;我们的数据可以分为三类&#xff1a;结构化数据、非结构化数据、半结构化数据。 结构化数据&#xff1a;一般会用特定的结构来组织和管理数据&#xff0c;表现为二维表结构。…

【Android常见问题(五)】- Flutter项目性能优化

文章目录 知识回顾前言源码分析1. 渲染过程2. 分析工具3. 优化方法合理使用const关键词合理使用组件管理着色器编译垃圾 知识回顾 前言 项目迭代开发一定程度后&#xff0c;性能优化是重中之重&#xff0c;其中包括了包体积&#xff0c;UI 渲染、交互等多个方面。 通过 Flutt…

码农该如何延长周末体验感

码农该如何延长周末体验感 码农该如何延长周末体验感 码农该如何延长周末体验感1.制定合理的工作计划&#xff1a;2.实践工作与生活的平衡&#xff1a;3.学习新技术或扩展知识领域4.参与开源项目或个人项目&#xff1a;5.与同事或朋友组织活动&#xff1a;6.自己写博客或者总结…

百万数据快速导入导出

百万数据快速导入 pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>Resourceprivate SalariesListener salariesListener;private ExecutorService…

求解方程x^2=a的根,不使用库函数直接求解(不动点迭代法)

首先可以将方程两边同时加上x&#xff0c;&#xff0c;这时候两边同时再除以1x&#xff0c;就得到了&#xff0c;变形为。&#xff08;变性后的迭代式不唯一&#xff0c;这里随便选取一个&#xff09; 当x是准确值的时候&#xff0c;两边应该是相等的&#xff0c;如果x是近似值…

【Git】分支管理之创建、切换、合并、删除分支以及冲突处理

目录 一、理解分支 二、创建、切换、合并分支 三、删除分支 四、冲突处理 五、合并模式 六、合并策略 七、Bug分支处理 八、强制删除分支 一、理解分支 master其实就是一个指针 &#xff0c;他指向的是主分支最近一次commit。我们可以创建新的分支&#xff0c;在新的分…

Arcgis之 KML/KMZ文件转shp

一般我们在Goole Earth上勾画的区域导出后都为KML或者KMZ格式的&#xff0c;但无法在arcgis等软件上直接应用&#xff0c;故需进行一定的转换 1.打开ArcMap&#xff0c;选择ArcToolbox->Conversion Tools->From KML->KML To Layer 得到如下结果&#xff08;由于本KML…

请问学JavaScript 前要学html 和css 吗?

前言 html和css可以理解为是一个网站的骨架和皮肤&#xff0c;这两部分做好后整个网站的外观展示的完成度基本就有了个90%左右&#xff0c;所以在学习js前是需要学习html和css 的&#xff0c;这两部分不用花特别多的时间&#xff08;虽然css如果想做一些非常炫酷的效果个人认为…

什么是SVM算法?硬间隔和软间隔的分类问题

SVM全称是supported vector machine(支持向量机)&#xff0c;即寻找到一个超平面使样本分成两类&#xff0c;并且间隔最大。 SVM能够执行线性或⾮线性分类、回归&#xff0c;甚至是异常值检测任务。它是机器学习领域最受欢迎的模型之一。SVM特别适用于中小型复杂数据集的分类。…

MobaXterm通过SSH访问Ubuntu服务器遇到的一个问题

在Windows下的MobaXterm界面配置完ubuntuIP以后显示access denied&#xff0c;排查发现是因为在ubuntu那边忘记安装了SSH Serve&#xff0c;安装过程如下&#xff1a; 第一步&#xff1a;安装所需包 让我们从打开终端输入一些必要命令开始。 注意&#xff0c;在安装新的包或…

SpringBoot统一异常处理和统一返回格式

上篇博客我们讲解了使用AOP来进行统一的用户登录判断&#xff0c;其实像这种功能统一且使用较多的地方&#xff0c;都可以用AOP来处理&#xff0c;除了统⼀的⽤户登录判断之外&#xff0c;AOP 还可以实现&#xff1a; 统⼀⽇志记录统⼀⽅法执⾏时间统计&#xff08;在性能优化…

机器学习:混合高斯聚类GMM(求聚类标签)+PCA降维(3维降2维)习题

使用混合高斯模型 GMM&#xff0c;计算如下数据点的聚类过程&#xff1a; Datanp.array([1,2,6,7]) 均值初值为: μ1,μ21,5 权重初值为: w1,w20.5,0.5 方差: std1,std21,1 K2 10 次迭代后数据的聚类标签是多少&#xff1f; 采用python代码实现&#xff1a; from scipy import…

人工智能-Dlib+Python实现人脸识别(人脸识别篇)

人脸识别流程 人脸检测,人脸数据提取:首先是检测到人脸保存人脸数据:可以保存到mysql数据库中mysql数据库连接mysql数据库安装mysql数据库操作设置人脸数据标签:(人脸名字),保存到数据库打开摄像头,检测到人脸,提取人脸数据:人脸数据与数据库中的数据对比,1、人脸检…

【图论】Prim算法

一.介绍 Prim算法是一种用于解决最小生成树问题的贪心算法。最小生成树问题是指在一个连通无向图中找到一个生成树&#xff0c;使得树中所有边的权重之和最小。 Prim算法的基本思想是从一个起始顶点开始&#xff0c;逐步扩展生成树&#xff0c;直到覆盖所有顶点。具体步骤如下…

用合成数据训练托盘检测模型【机器学习】

想象一下&#xff0c;你是一名机器人或机器学习 (ML) 工程师&#xff0c;负责开发一个模型来检测托盘&#xff0c;以便叉车可以操纵它们。 ‌你熟悉传统的深度学习流程&#xff0c;已经整理了手动标注的数据集&#xff0c;并且已经训练了成功的模型。 推荐&#xff1a;用 NSDT设…

【业务功能篇60】Springboot + Spring Security 权限管理 【终篇】

4.4.7 权限校验扩展 4.4.7.1 PreAuthorize注解中的其他方法 hasAuthority&#xff1a;检查调用者是否具有指定的权限&#xff1b; RequestMapping("/hello")PreAuthorize("hasAuthority(system:user:list)")public String hello(){return "hello Sp…

深度学习入门教程(1):用神经网络预测糖尿病病例Predict Diabetes Cases with Neural Networks

本深度学习入门教程是在polyu HPCStudio 启发以及资源支持下进行的&#xff0c;在此也感谢polyu以及提供支持的老师。 大纲&#xff08;what will you learn from this project&#xff09; 1&#xff1a;What are neural networks&#xff1f; 2&#xff1a;Why use neural …

3D 渲染技巧-如何创建高质量写实渲染?

掌握创建高质量建筑渲染和任何 3D 渲染的艺术是一项复杂且需要技巧的工作&#xff0c;通常需要多年的经验和实践。实现逼真的结果需要仔细考虑众多因素&#xff0c;并避免可能导致缺乏真实性的假渲染效果的常见错误。 避免常见错误 - 提升渲染游戏的技巧 在追求创建真正逼真的…