[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.mzph.cn/news/13432.shtml

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

相关文章

【leetcode】7.28记录

题目考察内容思路踩坑167. 两数之和 II - 输入有序数组 (Easy)双指针双指针分别指向首尾&#xff0c;判断指针两数之和与target的关系633. 平方数之和(Medium)双指针从0到sqrt(target)判断两数可以相同&#xff0c;为了避免溢出可以使用long345. 反转字符串中的元音字母双指针将…

平均列顺序对列排斥能的影响

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;AB训练集各由5张二值化的图片组成&#xff0c;让A有6个1&#xff0c;B有4个1&#xff0c;并且让这10个1的位置没有重合。比较迭代次数的顺序。 其中有9组数据 差值结构 A-B 迭代次数 构造平均列 …

使用PyGWalker可视化分析表格型数据

大家好&#xff0c;可以想象一下在Jupyter Notebook中拥有大量数据&#xff0c;想要对其进行分析和可视化。PyGWalker就像一个神奇的工具&#xff0c;能让这项工作变得超级简单。它能获取用户的数据&#xff0c;并将其转化为一种特殊的表格&#xff0c;可以与之交互&#xff0c…

ES6 - promise.all和race方法的用法详解

文章目录 一、前言二、Promise.all()1&#xff0c;第一句&#xff1a;Promise.all()方法接受一个数组作为参数&#xff0c;且每一个都是 Promise 实例2&#xff0c;第二句&#xff1a;如果不是&#xff0c;就会先调Promise.resolve方法&#xff0c;将参数转为 Promise 实例再进…

pytorch的发展历史,与其他框架的联系

我一直是这样以为的&#xff1a;pytorch的底层实现是c(这一点没有问题&#xff0c;见下边的pytorch结构图),然后这个部分顺理成章的被命名为torch,并提供c接口,我们在python中常用的是带有python接口的&#xff0c;所以被称为pytorch。昨天无意中看到Torch是由lua语言写的&…

第二篇-二手工作站配置-AI-LLM

把二手T5810升级了一下用于大模型测试 主机T5810CPUE5-2680V4 14核28线程内存DDR4 16G *4显卡1GT720显卡2Tesla P40 24G硬盘爱国者SSD 2T电源825W 系列文章 第一篇-ChatGLM-webui-Windows安装部署-CPU版 第二篇-二手工作站配置 第三篇-Tesla P40CentOS-7CUDA 11.7 部署实践 …

【如何训练一个中英翻译模型】LSTM机器翻译模型部署(三)

系列文章 【如何训练一个中英翻译模型】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型部署&#xff08;三&#xff09; 【如何训…

Windows Server 2012 能使用的playwright版本

由于在harkua_bot里面使用到了playwright&#xff0c;我的服务器又是Windows Server 2012 R2&#xff0c;最新版playwright不支持Windows Server 2012 R2&#xff0c;支持Windows Server 2016以上&#xff0c;所以有了这个需求 https://cdn.npmmirror.com/binaries/playwright…

Hadoop生态体系-HDFS

目录标题 1、Apache Hadoop2、HDFS2.1 设计目标&#xff1a;2.2 特性&#xff1a;2.3 架构2.4 注意点2.5 HDFS基本操作2.5.1 shell命令选项2.5.2 shell常用命令介绍 3、HDFS基本原理3.1 NameNode 概述3.2 Datanode概述 1、Apache Hadoop Hadoop&#xff1a;允许使用简单的编程…

Android Hook 剪切板相关方法

想起之前做过的项目有安全合规要求&#xff1a;主动弹窗获取用户同意了才能调用剪切板相关方法&#xff0c;否则属于违规调用&#xff0c;如果是自己项目的相关调用可以自己加一层if判断 但是一些第三方的jar包里面也有在调用的话&#xff0c;我们就无能为力了&#xff0c;而且…

el-table组件的el-table-column电脑端使用fixed属性固定,移动端不使用固定,怎么实现?

要在电脑端使用 fixed 固定列&#xff0c;而在移动端不使用&#xff0c;可以使用 CSS 媒体查询结合 Vue 的动态绑定来实现。以下是一个示例代码&#xff1a; <template><el-table><el-table-columnprop"name"label"Name":fixed"isDesk…

JPA连接达梦数据库导致auto-ddl失效问题解决

现象&#xff1a; 项目使用了JPA&#xff0c;并且auto-ddl设置的为update&#xff0c;在连接达梦数据库的时候&#xff0c;第一次启动没有问题&#xff0c;但是后面重启就会报错&#xff0c;发现错误为重复建表&#xff0c;也就是说已经建好的表没有检测到&#xff0c;…

title: 用 LangChain 构建基于资料库的问答机器人(四):通过代理使用外部工具

上一篇教程我们介绍了 ReAct 系统&#xff0c;这是一个非常强大的行为模式&#xff0c;但它需要编写大量的示例来告诉 LLM 如何思考、行动&#xff0c;并且为了遵循这个模式&#xff0c;还需要编写代码来分析生成文字、调用函数、拼接 prompt 等&#xff0c;这些工作都是十分繁…

JVM类加载

一、类记载过程 1、通过类的全限定名获取存储该类的class文件 2、解析成运行时数据&#xff0c;即instanceKlass实例&#xff0c;存放到方法区 3、在堆区生成该类的class对象,即instanceMirrorKlass实例 二、将.class文件解析成什么&#xff1f;类的元信息在JVM中如何…

ceph集群中RBD的性能测试、性能调优

文章目录 rados benchrbd bench-write测试工具Fio测试ceph rbd块设备的iops性能测试ceph rbd块设备的带宽测试ceph rbd块设备的延迟 性能调优 rados bench 参考&#xff1a;https://blog.csdn.net/Micha_Lu/article/details/126490260 rados bench为ceph自带的基准测试工具&am…

全加器(多位)的实现

一&#xff0c;半加器 定义 半加器&#xff08;Half Adder&#xff09;是一种用于执行二进制数相加的简单逻辑电路。它可以将两个输入位的和&#xff08;Sum&#xff09;和进位&#xff08;Carry&#xff09;计算出来。 半加器有两个输入&#xff1a;A 和 B&#xff0c;分别代表…

MySQL基础扎实——MySQL中有那些不同的表格

表格类型 在MySQL中&#xff0c;常见的表格类型有以下几种&#xff1a; MyISAM&#xff1a;是MySQL默认的表格类型&#xff0c;具有较高的性能和较小的存储空间占用。但是&#xff0c;MyISAM不支持事务、崩溃恢复和数据行级锁定。 InnoDB&#xff1a;是MySQL提供的一个更强大…

Redis实现分布式锁

文章目录 4、分布式锁4.1 、基本原理和实现方式对比4.2 、Redis分布式锁的实现核心思路4.3 实现分布式锁版本一4.4 Redis分布式锁误删情况说明4.5 解决Redis分布式锁误删问题4.6 分布式锁的原子性问题4.7 Lua脚本解决多条命令原子性问题4.8 利用Java代码调用Lua脚本改造分布式锁…

MySQL | 常用命令示例

MySQL | 常用命令示例 一、启停MySQL数据库服务二、连接MySQL数据库三、创建和管理数据库四、创建和管理数据表五、数据备份和恢复六、查询与优化 MySQL是一款常用的关系型数据库管理系统&#xff0c;广泛应用于各个领域。在使用MySQL时&#xff0c;我们经常需要编写一些常用脚…

python多线程—终止子线程

总体思路 1、获取需要终止的子线程id 2、根据子线程id&#xff0c;终止子线程。 过程 获取子线程id&#xff1a; import threading Thread_id threading.get_ident() # 获取子线程的id值线程终止函数 def async_raise(Thread_id, exctype):"""raises th…