【JavaEE多线程】Java 文件操作

目录

    • Java中操作文件
      • File概述
        • 属性
        • 构造方法
        • 方法
      • 文件内容的读写——文件流 stream
        • InputStream
        • FileInputStream概述
        • 利用 Scanner 进行字符读取
        • OutputStream 概述
      • 练习


Java中操作文件

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

文件系统操作

创建文件、删除文件、创建目录

通过File对象来描述一个具体的文件,File对象可以对应到一个真实存在的文件,也可以对应到一个不存在的文件

File概述

属性
修饰符及类型属性说明
static StringpathSeparator依赖于系统的路径分隔符,String 类型的表示
static charpathSeparator依赖于系统的路径分隔符,char 类型的表示
构造方法
签名说明
File(File parent, String child)根据父目录 + 孩子文件路径,创建一个新的 File 实例
File(String pathname)根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径
File(String parent, String child)根据父目录 + 孩子文件路径,创建一个新的 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()判断用户是否对文件有可写权限

观察 get 系列的特点和差异

//File的使用
public class Demo1 {public static void main(String[] args) throws IOException {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.getCanonicalFile());}
}//运行结果
.
test.txt
.\test.txt
C:\Users\幽琴健\java_Code\giteedemo\system_code\.\test.txt
C:\Users\幽琴健\java_Code\giteedemo\system_code\test.txt

普通文件的创建

public class Demo2 {public static void main(String[] args) throws IOException {File file=new File("./test.txt");//创建文件file.createNewFile();System.out.println(file.exists());System.out.println(file.isFile());System.out.println(file.isDirectory());}
}//运行结果
true
true
false

普通文件的删除

//文件删除
public class Demo3 {public static void main(String[] args) throws InterruptedException, IOException {File file =new File("./test.txt");System.out.println(file.createNewFile());//System.out.println(file.delete());//是等到程序退出了再删除,不是立即删除;file.deleteOnExit();System.out.println(file.exists());Thread.sleep(5000);}
}//运行结果
true
true

观察目录的创建1

public class Demo4 {public static void main(String[] args) {File file=new File("./testDir");// 要求该目录不存在,才能看到相同的现象System.out.println(file.mkdir());System.out.println(file.isDirectory());}
}//运行结果
true
true

观察目录的创建2

public class Demo4 {public static void main(String[] args) {File file=new File("./testDir/111/222/333");// 要求该目录不存在,才能看到相同的现象System.out.println(file.mkdirs());System.out.println(file.isDirectory());}
}//运行结果
true
true

观察文件重命名

//文件重命名
public class Demo5 {public static void main(String[] args) {File file=new File("./test.txt");File file2=new File("./test1.txt");System.out.println(file.renameTo(file2));}
}//运行结果
true

以上文件系统的操作,都是基于File类来完成的。另外还需要文件内容的操作

文件内容的读写——文件流 stream

文件这里的内容本质是来自于硬盘,硬盘又是操作系统管理的。使用某个编程语言操作文件,本质上都是需要调用系统的api

文件内容的操作核心步骤有四个:

  1. 打开文件 fopen
  2. 关闭文件 fclose
  3. 读文件 fread
  4. 写文件 fwrite

字节流:InputStream、OutputStream,是操作字节为单位(二进制文件)

字符流:Reader、Writer,是操作字符为单位(文本文件)

Java lO 流是一个比较庞大的体系,涉及到非常多的类。这些不同类,都有各自不同的特性但是总的来说,使用方法都是类似的。

  1. 构造方法,打开文件
  2. close方法,关闭文件。(可以通过finally或者**try()**的方式去关闭,后者更优雅)
  3. 如果衍生自InputStream或者Reader就可以使用read方法来读数据
  4. 如果衍生自OutputStream或者Writer就可以使用write方法来写数据

注意:close()方法这个释放必要的资源这个操作非常重要。让一个进程打开一个文件是要从系统这里申请一定的资源的(占用进程的PCB里的文件描述符表中的一个表项,这个表是个顺序表,长度有限且不会扩容),如果不释放就会出现“文件资源泄露”,如果一直打开,文件描述符表就会被占满,后续就无法继续打开新的文件了

文本文件也可以用字节流打开,只不过此时你读到的每个字节就不是完整的字符了

InputStream

方法

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

说明

InputStream 只是一个抽象类,要使用还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,我们现在只关心从文件中读取,所以使用FileInputStream

FileInputStream概述

构造方法

签名说明
FileInputStream(File file)利用 File 构造文件输入流
FileInputStream(String name)利用文件路径构造文件输入流
//Reader使用
public class Demo6 {public static void main(String[] args) throws IOException {
//        FileReader 构造方法, 可以填写一个文件路径(绝对路径/相对路径都行), 也可以填写一个构造好的 File 对象
//        Reader reader = new FileReader("d:/test.txt");
//        try {
//            // 中间的代码无论出现啥情况, close 都能保证执行到.
//        } finally {
//            // 抛出异常, 或者 return, close 就都执行不到了~~
//            reader.close();
//        }// 上述使用 finally 的方式能解决问题, 但是不优雅.// 使用 try with resources 是更好的解决方案.try(Reader reader=new FileReader("d:/test.txt")){while(true){char[] buf=new char[1024];int n=reader.read(buf);if(n==-1){//读到文件末尾了break;}for(int i=0;i<n;i++){System.out.print(buf[i]+" ");}}}}
}
public class Demo7 {public static void main(String[] args) throws IOException {try (InputStream inputStream = new FileInputStream("d:/test.txt")) {while (true) {byte[] buf = new byte[1024];int n = inputStream.read(buf);if (n == -1) {break;}for (int i = 0; i < n; i++) {System.out.printf("%x ", buf[i]);}String s = new String(buf, 0, n, "utf8");System.out.println(s);}}}
}
利用 Scanner 进行字符读取

上述例子中,我们看到了对字符类型直接使用 InputStream 进行读取是非常麻烦且困难的,所以,我们使用一种我们之前比较熟悉的类来完成该工作,就是 Scanner 类。

构造方法说明
Scanner(InputStream is, String charset)使用 charset 字符集进行 is 的扫描读取
public class Demo8 {public static void main(String[] args) throws IOException {try(InputStream inputStream=new FileInputStream("d:/test.txt")){Scanner scanner=new Scanner(inputStream);//此时就是从test.txt这个文件中读取数据了String s=scanner.next();System.out.println(s);}}
}
OutputStream 概述

方法

修饰符及返回值类型方法签名说明
voidwrite(int b)写入要给字节的数据
voidwrite(byte[] b)将 b 这个字符数组中的数据全部写入 os 中
intwrite(byte[] b, int off,int len)将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
voidclose()关闭字节流
voidflush()重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

说明

OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中,所以使用 FileOutputStream

public class Demo9_1 {public static void main(String[] args) throws IOException {try(OutputStream outputStream=new FileOutputStream("d:/test.txt")){outputStream.write('H');outputStream.write('e');outputStream.write('l');outputStream.write('l');outputStream.write('o');//不要忘记了 flsuh()outputStream.flush();}}
}

练习

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

public class Demo10 {private static Scanner scanner = new Scanner(System.in);public static void main(String[] args) {//1、让用户输入一个目录,后续的查找都是针对这个目录来进行的System.out.println("请输入要搜索的根目录:");File rootPath = new File(scanner.next());//2、再让用户输入要搜索/要删除的关键词System.out.println("请输入要删除的关键词:");String word = scanner.next();//3、判定一下当前要输入的目录是否有效if (!rootPath.isDirectory()) {System.out.println("您输入的路径不是合法目录");return;}//4、遍历目录,从根目录出发,按照深度优先(递归)的方式进行遍历scanDir(rootPath,word);}public static void scanDir(File curDir, String word) {//1、先列出当前目录中都包含哪些内容File[] files = curDir.listFiles();if (files == null || files.length == 0) {//非法目录或者空目录return;}//2、遍历列出的文件,分两种情况讨论for (File f : files) {//加个日志,方便查看程序执行的过程System.out.println(f.getAbsolutePath());if (f.isFile()) {//3、如果当前文件是普通文件,看看文件名是否包含了word,来决定是否要删除dealFile(f, word);} else {//4、如果当前文件是目录文件,就递归执行scanDirscanDir(f, word);}}}private static void dealFile(File f, String word) {//1、先判定当前文件名是否包含wordif (!f.getName().contains(word)) {//此时这个文件不包含word关键词,直接跳过return;}//2、包含word就需要询问用户是否需要删除该文件?System.out.println("该文件是:" + f.getAbsolutePath() + ",是否确认删除(Y/N)");String choice = scanner.next();if (choice.equals("Y") || choice.equals("y")) {f.delete();}//如果是其他值就忽略}
}//运行结果
请输入要搜索的根目录:
d:/tmp
请输入要删除的关键词:
test
d:\tmp\111
d:\tmp\111\aaa
d:\tmp\111\aaa\test.txt
该文件是:d:\tmp\111\aaa\test.txt,是否确认删除(Y/N)
n
d:\tmp\222
d:\tmp\222\bbb
d:\tmp\222\bbb\新建 文本文档.txt
d:\tmp\333
d:\tmp\333\ccc

进行普通文件的复制

public class Demo11 {public static void main(String[] args) throws IOException {Scanner scanner = new Scanner(System.in);//1、输入路径并且合法性判定System.out.println("请输入要复制的源文件路径:");String src = scanner.next();File srcFile = new File(src);if (!srcFile.isFile()) {System.out.println("您输入的源文件路径非法");return;}System.out.println("请输入要复制到的目标路径:");String dest = scanner.next();File destFile = new File(dest);//不要求目标文件本身存在. 但是得保证目标文件所在的目录, 得是存在的.//假设目标文件写作 d:/tmp/cat2.jpg, 就需要保证 d:/tmp 目录是存在的.if (!destFile.getParentFile().isDirectory()) {System.out.println("您输入的目标路径非法");return;}//2、进行复制操作的过程,按照字节流打开try (InputStream inputStream = new FileInputStream(srcFile);OutputStream outputStream = new FileOutputStream(destFile)) {while (true) {byte[] buffer = new byte[20480];int n = inputStream.read(buffer);System.out.println("n=" + n);if (n == -1) {System.out.println("读取到EOF,循环结束");break;}outputStream.write(buffer, 0, n);}}}
}//运行结果
请输入要复制的源文件路径:
d:/tmp/111/calculator.png
请输入要复制到的目标路径:
d:/tmp/222/calculator2.png
n=20480
n=220
n=-1
读取到EOF,循环结束

扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

public class Demo12 {public static void main(String[] args) throws IOException {Scanner scanner = new Scanner(System.in);System.out.println("请输入要扫描的根目录:");String rootPath = scanner.next();File rootDir = new File(rootPath);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) throws IOException {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());}}}}//我们全部按照utf-8的字符文件来处理private static boolean isContentContains(File file, String token) throws IOException {StringBuilder sb = new StringBuilder();try (InputStream inputStream = new FileInputStream(file)) {try (Scanner scanner = new Scanner(inputStream, "UTF-8")) {while (scanner.hasNextLine()) {sb.append(scanner.nextLine());sb.append("\r\n");}}}return sb.indexOf(token) != -1;}
}//运行结果
请输入要扫描的根目录:
d:/tmp
请输入要找出的文件名中的字符
hello
共找到了符合条件的文件 3 个,它们分别是:
D:\tmp\111\aaa\test.txt
D:\tmp\222\bbb\新建 文本文档.txt
D:\tmp\333\ccc\新建 文本文档.txt

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

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

相关文章

Ruby中Rack中间件的作用是什么?如何应用?

在 Ruby 中&#xff0c;Rack 是一个 Web 服务器接口&#xff0c;它允许开发者使用统一的方式构建 Web 应用程序。Rack 中间件是 Rack 框架的一个核心概念&#xff0c;它可以在请求被传递给应用程序之前或之后对请求和响应进行处理。 Rack 中间件的作用包括但不限于&#xff1a…

IPv6改造:反向代理技术的原理和优缺点分析

在前面几篇文章中&#xff0c;我们介绍了目前行业中三种比较常见的IPv6改造技术&#xff0c;分别是隧道技术、双栈技术和翻译技术&#xff0c;这三种改造方式采用不同的技术方案实现了IPv4向IPv6网络的过渡&#xff0c;然而每种改造技术在改造周期和成本、业务连续性、协议兼容…

实景景区亲自儿童剧本杀小程序开发搭建

实景景区亲自儿童剧本杀小程序开发搭建需要涉及多个方面的内容&#xff0c;包括系统架构设计、功能模块设计、页面设计、开发工具选择等。 系统架构设计需要确定小程序的开发框架&#xff0c;可以使用小程序开发框架来构建前端页面和后端接口&#xff0c;同时需要考虑数据库设…

ctfshow web入门 SQl注入 web185--web190

web185 这道题还有另外一个脚本就是用concat的拼接达到有数字的目的 concat(truetrue) 2 concat(true) 1 concat(true, true) 11 然后上脚本&#xff08;Y4tacker这个师傅的&#xff09; # Author:Y4tacker import requestsurl "http://341e93e1-a1e7-446a-b7fc-75beb…

目标检测——行人交通信号灯数据集

一、重要性及意义 行人交通信号灯检测的重要性及意义主要体现在以下几个方面&#xff1a; 首先&#xff0c;行人交通信号灯检测对于提高道路安全性至关重要。通过准确识别交通信号灯的状态&#xff0c;行人可以更加清晰地了解何时可以安全地过马路&#xff0c;从而避免与车辆…

node.js版本降级/升级

第一步.先清空本地安装的node.js版本 按健winR弹出窗口&#xff0c;键盘输入cmd,然后敲回车&#xff08;或者鼠标直接点击电脑桌面最左下角的win窗口图标弹出&#xff0c;输入cmd再点击回车键&#xff09; 进入命令控制行窗口&#xff0c;输入where node&#xff0c;查看本地…

Android Studio历史版本下载地址

https://developer.android.com/studio/archive?hlzh-cn https://blog.csdn.net/crasowas/article/details/130304836

STM32F4使用FPU/DSP核心启用与测试

STEP1、下载DSP库 具体链接如下&#xff1a; https://www.st.com/en/embedded-software/stsw-stm32065.html?dl9w6sdOSAKySFxBhN764Stg%3D%3D%2CIS1vzyA84KLAefK%2B0DawUl0FScREpiT6AdC3qFjIMJnCIgXIwr82G2XUFo6w43Wp5L5CUyrX3vZAoaHRE3nsTmRsArV3hnQOEgX73SKt8ss1vGrLlfXT24j…

【electron 4】electron配置打包环境

首先要准备应用图标 window需要&#xff1a;ico mac需要&#xff1a;icns linux需要png 借助&#xff1a;electron-icon-builder 安装&#xff1a; npm i electron-icon-builder -D配置package.json scripts "build-icon": "electron-icon-builder --input.…

js获取某月往前推一年或半年的年月数组

前言 需求&#xff1a;需要显示某月份往前推一年或者半年的费用情况&#xff0c;显示到柱形图上&#xff0c;后台接口只返回有数据的年份&#xff0c;这就需要前端拿全部月份数组去比对并显示。 开始 上代码&#xff1a; // date:选择的月份,比如:2024-04,//n:半年或者1年,…

完美解决多种情况下的 java.lang.NullPointerException 的异常

文章目录 1. 复现错误2. 分析问题3. 解决问题1. 复现错误 在工作中,经常会遇见java.lang.NullPointerException的异常,这种异常千奇百怪,但明确一点的是:它是空指针异常,也称之为NPE异常,如下代码所示: @Setter @Getter @Accessors(chain = true) public class Student…

【UE5.1 C++】VS2022下载安装

目录 步骤 一、Visual Studio下载安装 二、Visual Studio Integration Tool插件安装 先看一下UE和VS的兼容性 &#xff08;虚幻5&#xff1a;为虚幻引擎C项目设置Visual Studio开发环境&#xff09; &#xff08;虚幻4&#xff1a;设置虚幻引擎的Visual Studio&#xff0…

XiaodiSec day022 Learn Note 小迪安全学习笔记

XiaodiSec day022 Learn Note 小迪安全学习笔记 记录得比较凌乱&#xff0c;不尽详细 day22 主要内容 原生 js 款该 前端验证&未授权 开始 js 中也存在变量和函数&#xff0c;在浏览器中可以直接从浏览器中解析出&#xff0c;相当于白盒 而在之前的类似于 java 或 P…

libxml2读写XML文件测试

libxml2是一个功能强大的XML解析库&#xff0c;可以用于读取和写入XML文件。以下是一些基本的例子来展示如何使用libxml2进行读写操作。 写文件 在这个例子中&#xff0c;我们首先创建一个新的XML文档&#xff0c;并设置一个根节点。然后&#xff0c;我们创建两个新的节点&…

大型网站系统架构演化实例_6.使用分布式文件系统和分布式数据库系统

1.使用分布式文件系统和分布式数据库系统 任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库经过读写分离后&#xff0c;从一台服务器拆分成两台服务器&#xff0c;但是随着网站业务的发展依然不能满足需求&#xff0c;这时需要使用分布式数据库。文件系统也一…

3dmax安装错误代码2146885616,也出现以下可选组件未成功安装:-Substance

当3dmax高版本出现安装错误代码2146885616&#xff0c;或者可选组件未成功安装:-Substance时&#xff0c;如图 解决方法如下 打开autoremove&#xff0c;点击扩展功能&#xff0c;搜索2146885616点击搜索 点击出现的按钮&#xff0c;提示如图&#xff0c;请重启电脑再点击一…

html网页在展示时,监听网络是否断网,如果断网页面暂停点击响应

序言&#xff1a; 集合百家之所长&#xff0c;方著此篇文章&#xff0c;废话少说&#xff0c;直接上代码&#xff0c;找好你的测试网页&#xff0c;进行配置&#xff0c;然后复制粘贴代码&#xff0c;就可以了。 1.css文件内容 #newbody{display: none;width: 100%;height: 9…

24V转2.8V2A降压芯片WT6030

24V转2.8V2A降压芯片WT6030 WT6030是一种高效同步整流降压开关模式转换器&#xff0c;集成内部功率MOSFET。该器件在宽输入电源范围内提供3A峰值输出电流&#xff0c;展现出卓越的负载和线路调节性能。其设计仅需要最小数量的外部现成组件&#xff0c;并且采用了节省空间的ESO…

Dubbo的服务注册与发现是如何实现的?注册中心的作用是什么?

Dubbo的服务注册与发现机制及注册中心的作用 在微服务架构中&#xff0c;服务注册与发现是一个至关重要的环节&#xff0c;它负责维护服务提供者和消费者之间的动态关系&#xff0c;确保服务调用能够顺利进行。Dubbo作为一款高性能、轻量级的开源Java RPC框架&#xff0c;其服…