【Java EE初阶十一】文件操作(IO)

1. 认识文件

        所谓的文件是一个广义的概念,可以代表很多东西;在操作系统里面,会把很多的硬件设备和软件设备都抽象成“文件”,统一进行管理;但是大部分情况下,我们读到的文件,都是指硬盘的文件,文件就相当于是针对“硬盘”数据的一种抽象;

1.1 简单了解硬盘

1.1.1 机械硬盘HDD

1.1.2 固态硬盘SSD

        固态硬盘里面就都是集成程度很高的芯片,且固态硬盘就要比机械硬盘的效率高很多; 

        我们在进行服务器开发的过程中,涉及到的硬盘有的是机械硬盘有的是固态硬盘,特别是一些用来存储大规模数据的机器,任然是机械硬盘为主,但是固态硬盘的读写速速要比内存慢很多;

内存和硬盘的区别:

  1. 内存的速度快,硬盘的速度慢;
  2. 内存的空间小,硬盘的空间大
  3. 内存贵,硬盘便宜;
  4. 内存的数据,断电就丢失,硬盘的数据断电还在

 1.1.3 文件的操作方式

        文件的操作方式是通过操作硬盘来实现的,一台计算机上有很多的文件,这些文件是通过“文件系统”(有由操作系统所提供的模块)来进行组织的,操作系统使用“目录”这样的结构来组织文件;

        即可以使用目录的层次结构(路径)来描述文件所在的位置

        F:\B站下载\【水灰】我们再一起去迪士尼吧

        如上所示的一个字符串,体现了当前文件在哪个目录中。

  1. 绝对路径:就是以C,D盘开头的,这种路径成为“绝对路径”
  2. 相对路径:需要先指定一个目录,从基准目录出发,看看沿啥样的路径能够找到指定文件,此时所涉及的路径就是“相对路径”,

1.2 文件的类型

        从编程的角度来看,文件类型,主要是两大类:

        1、文本(文件中保存的数据,都是字符串,保存的内容都是合法的字符串)

        2、二进制(文件中保存的数据,仅仅是二进制数据,不要求保存的内容是合法的字符)

        合法的字符->字符集/字符编码(主流的就是utf8,一个规定的表格,里面规定了什么样的字符对应什么样的编码),如果我们的文件时utf8编码的,此时文件中的每一个数据都是合法的utf8编码的字符,就可以认为这个文件是文本文件了;如果存在一些不是utf8合法字符的情况,就是二进制文件了;

        本身计算机存储的数据都是二进制的;

        如何判定一个文件时文本文件还是二进制文件?

        直接使用记事本来打开文件,如果打开之后是乱码,文件是二进制文件;否则是文本文件,记事本就是尝试按照字符的方式来展示内容,这个过程就会自动查码表,如下图所示:

        很多文件都是二进制的文件,docx,png……等文件都属于二进制文件;区分文本文件和二进制文件是十分重要的;我们在写代码的时候,文本文件和二进制文件,代码编写的方式是不同的;

        Java针对文件的操作,分成两类:

        1、针对文件系统的操作-> File

        即创建文件,删除文件,判定文件是否存在,判定文件类型,重命名

        2、针对文件内容的操作->流对象

       即读文件,写文件;

2. File 概述

2.1 file的属性

2.2 file类的构造方法

        一个file对象,就表示一个硬盘上的文件,在构造对象的时候,就需要把这个文件的路径指定进来(使用绝对、相对路径都可以)

        File提供的核心方法:文件名=前缀+扩展名->使用路径构造file对象,一定要把前缀和扩展名都写上;一个文件系统上都会对文件有权限的限制(约定了这个文件,那些用户可以读,那些用户可以写),我们是创建file对象的时候,就会使用到java提供的import java.io.File;该包里面的io分别表示:

        I:input

        0:output

2.3 file的相关方法

        一般来说,在使用文件的内容访问时候,io操作都需要抛出import java.io.IOException;下图是关于file类方法的调用:

q:关于下图输出的数值是文件的内存地址吗?

a:首先在jvm上层,java代码中是没有任何方法获取到“内存地址”的,想要获取内存地址,只能靠native方法,进入jvm内部,通过c++代码获取到;其次我们获取到的字符串是哈希值,是通过调用hashcode的方法获取到的

3. 流对象

        基于文件数据传输的特点,将文件中传输的数据称之为“文件流”

        在标准库中,提供的读写文件的流对象,不是一两个类,而是有很多类,但是实际上可以吧这么多类归结于两个类中:

        1、字节流:(对应着二进制文件)

        每次读写的最小单位是字节(8bit)

        提供了两个父类:inputstream,outputstream

        提供了两个父类:reader,writer

        2、字符流:(对应着文本文件)

        每次读写的最小单位是字符(一个字符对应很多个字节,主要是取决于当前的读取对象的字符集,gbk中一个中文字符对应两个字节;utf8中一个中文字符对应3个字节)

        字符流本质上是对字节流进行了又一层封装,字符流,就能够自动的帮我们把文件中的几个相邻的字节,转换成一个字符(帮我们完成了一个自动差字符集表)

        3、关于输入和输出的识别:

        论将数据保存到硬盘中,这个过程是输入还是输出?

        1、站在硬盘的角度,输入

        2、站在cpu的角度,输出;(我们要带入到cpu的视角)

3.1 reader 概述 

        Reader是一个抽象类,不能new实例,只能new一个子类,java标准库提供了一个现成的类filereader类。其创建方法如下图所示:

        创建reader对象的过程,就是“代开文件”的过程,下面是关于reader的三种方法:

        1、五参数read:一次只读取一个字符;

        2、一个参数read:一次读取若干个字符,回答参数指定的cbuf数组给填充满

        3、三个参数read:一次读取若干个字符,回答参数指定的cbuf数组中的从off这个位置开始,到len这么长的范围内尽量填满;代码细节如下所示:

 

         在java标准库内部,对于字符编码是进行了很多处理工作的,如果只使用char,此时使用的字符集,固定的就是unicode;如果是使用string,此时就会自动的把每一个unicode转换为utf8;

        char【】 c ->包含的每一个字符都是unicode,一旦使用这个字符数组构造成string,string s = new string(c),就会在内部把每一个字符都转换成utf8 

        把多个unicode连续放到一起,是很难区分从哪里到哪里地一个完整的字符的,utf8是可以做到区分的;utf8可以认为是针对连续多个字符进行传输时候的一种改进方案

        对于reader.read( )这个方法里面,应该是往这个read里面传入的是一个空的字符数组(不是null,而是没有实际意义数据的数组),然后由read方法内部,对这个数组内容进行填充,此时的cbuf这个参数,称为“输出型参数”

 

        如果文件为空,就直接返回-1了;

        当一个文件读取完了之后,我们要记得进行关闭close,使用colse方法,最主要的就是为了释放文件描述符;

        pcb这里会包含很多的属性:pid,内存指针,文件描述符表(本质上是由数组构成的顺序表),一个进程每一次打开一个文件,就需要早这个表里分配一个元素,但是这个数组的长度是有限的,如果我们的代码中在运行的过程中,一直在进行打开文件而不能及时的关闭,就会是这个表里面的元素越来越多,最终就昂这个数组沾满,后续在尝试打开文件就会出现报错;

        这样的错误就是文件资源泄露,类似于内存泄漏,在java中我们打开的文件还是需要我们进行手动释放的,此时的代码如下所示:

package io;import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;// Reader
public class Demo7 {public static void main(String[] args) throws IOException {Reader reader = new FileReader("d:/test.txt");// 2. 一次 read 多个字符while (true) {char[] cbuf = new char[3];// n 表示当前读到的字符的个数.int n = reader.read(cbuf);if (n == -1) {// 读取完毕break;}System.out.println("n = " + n);for (int i = 0; i < n; i++) {System.out.println(cbuf[i]);}}// 3. 一个文件使用完了, 要记得, close !!!reader.close();              }
}

        但是代码如上所示,我们的代码依旧存在文件资源泄露的风险,因为如果我们的代码在前期出现逻辑异常而进行抛出异常处理的话,就执行不到close方法,所以对上述代码进行改进处理,如下图所示:

 3.2 writer 概述

        writer对象主要是写入文件,默认情况下就会把原有的文件内容清空掉,如果不想清空,就需要在构造方法中加个参数,如下图所示;

        关于write方法的种类如下图所示:

         System.in ====》inputstream; 

        关于write部分代码如下所示:

package io;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;public class Demo12 {public static void main(String[] args) {try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {// 这就相当于把字符流转成字节流了.PrintWriter writer = new PrintWriter(outputStream);writer.println("hello");writer.flush();} catch (IOException e) {e.printStackTrace();}}
}

        代码分析:

        缓冲区:printwriter这样的类,在进行写入的时候,不一定直接写入硬盘,而是先把数据写在一个内存构成的“缓冲区”中(buffer)

        我们引入缓冲区,目的是为了提高效率;把数据写入内存是非常快的;把数据写到硬盘,是非常慢的;

        这样会导致一个新的问题:当我们写入缓冲区后,如果还没来得及把缓冲区里的数据写进硬盘,进程就结束了,此时数据就会丢失;没有正真的写入硬盘;(进程结束,该内存就会释放)->为了确保数据会被写入硬盘,就应该在合适的时机,使用flush方法进行手动刷新缓冲区;

        该fiush操作,可以理解为“刷新缓冲区”,将我们存放在内存缓冲区中的数据冲刷到硬盘中;

4. 代码实例

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

4.1 案例分析

        文件系统操作:

        1、list列出目录内容

        2、判定文件的类型

        3、删除文件

所谓的扫描指定文件,就是找到目录中的所有文件,以及子目录中的所有文件,只要遇到子目录都能往里面找->采用递归的方式,把所有的子目录都给扫描一遍;

4.2 代码实现

package io;import java.io.File;
import java.util.Scanner;public class Demo13 {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 1. 先让用户输入一个要扫描的目录System.out.println("请输入要扫描的路径: ");String path = scanner.next();File rootPath = new File(path);if (!rootPath.isDirectory()) {System.out.println("您输入的扫描的路径有误!! ");return;}// 2. 再让用户输入一个要查询的关键词.System.out.println("请输入要删除文件的关键词: ");String word = scanner.next();// 3. 可以进行递归的扫描了.//    通过这个方法进行递归.scanDir(rootPath, word);}private static void scanDir(File rootPath, String word) {// 1. 先列出 rootPath 中所有的文件和目录.File[] files = rootPath.listFiles();if (files == null) {// 当前目录为 null, 就可以直接返回了.return;}// 2. 遍历这里的每个元素, 针对不同类型做出不同的处理.for (File f : files) {// 加个日志, 方便观察当前递归的执行过程.System.out.println("当前扫描的文件: " + f.getAbsolutePath());if (f.isFile()) {// 普通文件. 检查文件是否要删除. 并执行删除动作.checkDelete(f, word);} else {// 目录. 递归的再去判定子目录里包含的内容scanDir(f, word);}}}private static void checkDelete(File f, String word) {if (!f.getName().contains(word)) {// 不必删除, 直接方法结束return;}// 需要删除System.out.println("当前文件为: " + f.getAbsolutePath() + ", 请确认是否要删除(Y/n): ");Scanner scanner = new Scanner(System.in);String choice = scanner.next();if (choice.equals("Y") || choice.equals("y")) {// 真正执行删除操作f.delete();System.out.println("删除完毕!");} else {// 如果输入其他值, 不一定非得是 n, 都会取消删除操作.System.out.println("取消删除!");}}
}

ps:本篇的内容到这里就结束了,如果感兴趣的话就请一键三连哦!!!

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

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

相关文章

Codeforces Round 106 D. Coloring Brackets 【区间DP + 记忆化搜索实现】

D. Coloring Brackets 约定 ∣ S ∣ ≤ 700 |S| \leq 700 ∣S∣≤700 题意 给定一个正则括号序列 s s s&#xff0c;我们需要求出合法的染色方案数。合法的条件为&#xff1a; 每个符号要么不染色&#xff0c;要么染红色&#xff0c;要么染蓝色对于每对配对的括号&#xf…

单片机与外设的交互

单片机与外设的交互是嵌入式系统中非常重要的一个基础知识点。单片机是一个集成在同一芯片上的中央处理器、存储器和输入/输出接口,它可以根据用户编写的程序与各种外部设备即外设进行交互。单片机与外设之间的交互主要通过单片机上的输入/输出口(I/O口)来实现。 I/O口的工作原…

【golang】24、go get 和 go mod:indrect 与 go mod tidy

文章目录 go get 会执行如下操作&#xff1a; 操作 go.mod 文件&#xff08;add、update、remove&#xff09;下载依赖到 $GOPATH/pkg/mod 中若已安装&#xff0c;则更新该包&#xff0c;到最新版本 试验前置准备&#xff1a;首先删除已下载的依赖&#xff0c;rm -rf $GOPATH…

零基础学python之高级编程(1)---面向对象编程及其类的创建

面向对象编程及其类的创建 文章目录 面向对象编程及其类的创建前言一、面向过程编程和面向对象编程的概念1.面向过程编程(Procedural Programming)2.面向对象编程(Object-Oriented Programming&#xff0c;OOP) 二、面向对象编程基础1.初识类(class)和对象调用方法 2.类中的两种…

Redis(三)主从架构、Redis哨兵架构、Redis集群方案对比、Redis高可用集群搭建、Redis高可用集群之水平扩展

转自 极客时间 Redis主从架构 redis主从架构搭建&#xff0c;配置从节点步骤&#xff1a; 1、复制一份redis.conf文件2、将相关配置修改为如下值&#xff1a; port 6380 pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件 logfile "6380.log" …

JAVA设计模式之策略模式详解

策略模式 1 策略模式概述 策略模式(strategy pattern)的原始定义是&#xff1a;定义一系列算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。 其实我们在现实生活中常常遇到实现某种目标存在多种策略…

【机器学习】机器学习简单入门

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步…

CSP-202112-2-序列查询新解

CSP-202112-2-序列查询新解 【70分思路】 【暴力枚举】按照题目思路遍历一遍f(x)和g(x)&#xff0c;计算error(A)&#xff0c;时间复杂度为O(N)&#xff0c;时间超限。 #include <iostream> using namespace std; int main() {long long n, N, sum 0;cin >> n …

【SpringBoot】application配置(5)

type-aliases-package: com.rabbiter.cm.domaintype-aliases-package: 这个配置用于指定mybatis的别名&#xff0c;别名是一个简化的方式&#xff0c;让你在Mapper xml 文件中引用java类型&#xff0c;而不需要使用使用完整的类名。例如&#xff0c;如果你在 com.rabbiter.cm.d…

谷歌 DeepMind 联合斯坦福推出了主从式遥操作双臂机器人系统增强版ALOHA 2

谷歌 DeepMind 联合斯坦福推出了 ALOHA 的增强版本 ——ALOHA 2。与一代相比&#xff0c;ALOHA 2 具有更强的性能、人体工程学设计和稳健性&#xff0c;且成本还不到 20 万元人民币。并且&#xff0c;为了加速大规模双手操作的研究&#xff0c;ALOHA 2 相关的所有硬件设计全部开…

数据结构|对称矩阵压缩存储的下标公式推导|如何求对称矩阵压缩存储对应的一维数组下标

因为考试的时候可能会给很多情况的变式题&#xff0c;所以要会推导而不是背公式&#xff0c;情况变了&#xff0c;公式就不管用了。 行优先、只存储主对角线下三角区&#xff1a; 矩阵下标 ai,j(i>j)->一维数组下标 B[k] 按照行优先的原则&#xff0c;确定 ai,j 是一维数…

搭建yum仓库服务器

安装 1.安装linux 1.1安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 1.2下载 cd /opt/nginx wget http://nginx.org/download/nginx-1.25.3.tar.gz 1.3解压 tar -xvf nginx-1.25.3.tar.gz 1.4配置 cd nginx-1.25.3 ./configure --pre…

NLP_引入注意力机制

文章目录 点积注意力创建两个张量x1和x2计算张量点积&#xff0c; 得到原始权重对原始权重进行归一化求出注意力分布的加权和 缩放点积注意力编码器-解码器注意力定义Attention类重构Decoder类重构Seq2Seq类可视化注意力权重 注意力机制中的 Q、K、V自注意力多头自注意力注意力…

【MATLAB】使用随机森林在回归预测任务中进行特征选择(深度学习的数据集处理)

1.随机森林在神经网络的应用 当使用随机森林进行特征选择时&#xff0c;算法能够为每个特征提供一个重要性得分&#xff0c;从而帮助识别对目标变量预测最具影响力的特征。这有助于简化模型并提高其泛化能力&#xff0c;减少过拟合的风险&#xff0c;并且可以加快模型训练和推理…

阿里云游戏服务器租用价格表,2024最新报价

阿里云游戏服务器租用价格表&#xff1a;4核16G服务器26元1个月、146元半年&#xff0c;游戏专业服务器8核32G配置90元一个月、271元3个月&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云游戏专用服务器详细配置和精准报价&#xff1a; 阿里云游戏服务器租用价格表 阿…

【Linux系统学习】5.Linux实用操作 下

7.虚拟机配置固定IP 7.1 为什么需要固定IP 当前我们虚拟机的Linux操作系统&#xff0c;其IP地址是通过DHCP服务获取的。 DHCP&#xff1a;动态获取IP地址&#xff0c;即每次重启设备后都会获取一次&#xff0c;可能导致IP地址频繁变更 原因1&#xff1a;办公电脑IP地址变化无所…

顺序表、链表(ArrayList、LinkedList)

目录 前言&#xff1a; 顺序表&#xff08;ArrayList&#xff09;&#xff1a; 顺序表的原理&#xff1a; ArrayList源码&#xff1a; 的含义&#xff1a;​编辑 ArrayList的相关方法&#xff1a;​编辑 向上转型List&#xff1a; 练习题&#xff08;杨辉三角&#x…

Go 语言中如何大小端字节序?int 转 byte 是如何进行的?

嗨&#xff0c;大家好&#xff01;我是波罗学。 本文是系列文章 Go 技巧第十五篇&#xff0c;系列文章查看&#xff1a;Go 语言技巧。 我们先看这样一个问题&#xff1a;“Go 语言中&#xff0c;将 byte 转换为 int 时是否涉及字节序&#xff08;endianness&#xff09;&#x…

《Git 简易速速上手小册》第4章:Git 与团队合作(2024 最新版)

文章目录 4.1 协作流程简介4.1.1 基础知识讲解4.1.2 重点案例&#xff1a;为 Python Web 应用添加新功能4.1.3 拓展案例 1&#xff1a;使用 CI/CD 流程自动化测试4.1.4 拓展案例 2&#xff1a;处理 Pull Request 中的反馈 4.2 使用 Pull Requests4.2.1 基础知识讲解4.2.2 重点案…

MES生产制造管理:汽车零部件生产MES解决方案

某某汽车部件科技有限公司是一家铝合金零部件研发、压铸和精加工为一体的高新技术企业,拥有先进压铸、机加、检测等设备,并配套自动化生产线。为解决发动机支架等产品的全程生产质量追溯和实现机台设备联网,梅施科技提供了车间级的MES解决方案,如图所示&#xff1a; 梅施科技采…