【Java】文件操作与IO

news2024/11/22 17:21:36

文件操作与IO

    • Java中操作文件
      • 针对文件系统的操作
      • File类概述
        • 字段
        • 构造方法
        • 方法及示例
      • 文件内容的读写 —— 数据流
      • Java提供的 “流” API
      • 文件流读写文件内容
      • `InputStream` 示例
        • 读文件
          • 示例1:将文件完全读完的两种方式
          • 示例二:读取汉字
        • 写文件
          • 谈谈 `OutputStreamWriter` 和 `PrintWriter`
      • `Reader`
      • `Writer`
      • `Scanner` 辅助输入

Java中操作文件

Java对于文件操作的API:

  1. 针对文件系统的操作
    包括但不限于:创建文件、删除文件、重命名文件、列出目录内容…

  2. 针对文件内容的操作
    读文件 / 写文件


针对文件系统的操作

Java 使用 File 类来进行对文件系统的操作,这个类所在的包叫 java.io

解释一下IO:
I:input(输入)
O:output(输出)

对于计算机来说,CPU是最关键的部分,所以要坐在CPU的头上来看待问题:

  • 数据从硬盘到CPU,这个叫输入
  • 数据从CPU离开,这个叫输出

File类概述

字段

也就是路径之间的分隔符根据系统自动调整
在这里插入图片描述


构造方法

在练习中,使用第二个便够用了
![[Pasted image 20240117122431.png]]

注:如果写作相对路径,一定要明确其工作目录

  1. 如果直接在 idea 中运行程序,此时工作目录就是项目所在目录
  2. 如果把代码打包成一个单独的 jar 包来执行,此时工作目录就是 jar 包所在目录

方法及示例

![[Pasted image 20240117124331.png]]

绝对路径
![[Pasted image 20240117140533.png]]

相对路径
注意:这里使用的相对路径,只是在人的视角看是存在这一路径的。
但是这个路径信息很少,在编译器的角度上,这个路径是不存在
![[Pasted image 20240117141017.png]]


![[Pasted image 20240117124646.png]]

![[Pasted image 20240117141750.png]]

![[Pasted image 20240117142149.png]]

再运行一次:
![[Pasted image 20240117141941.png]]


deletedeleteOnExit

程序运行结束再删除,这样的文件,称为“临时文件

![[Pasted image 20240117142622.png]]


listlistFiles

PS:直接打印出来的,不叫“地址” ,是叫 “哈希值”
![[Pasted image 20240117204700.png]]

![[Pasted image 20240117204825.png]]

list ,获取到 “当前目录“ 下的所有文件名
![[Pasted image 20240117204932.png]]

listFiles,获取到 “当前目录” 下的所有文件名,但是是以 File 对象表示
![[Pasted image 20240117205135.png]]


这两个方法是用于创建目录
![[Pasted image 20240117124811.png]]

mkdir,只能创建一级目录
![[Pasted image 20240117205404.png]]

mkdirs:能创建多级目录
![[Pasted image 20240117205506.png]]


![[Pasted image 20240117124925.png]]

renameTo重命名
![[Pasted image 20240117205732.png]]

还有移动的功能(只能移动文件,不能移动目录)
![[Pasted image 20240117210416.png]]


文件内容的读写 —— 数据流

” 是操作系统中提出的概念,而编程语言基于这一概念抽象并封装出API来使用

什么叫抽象?

可以简单理解为:
信息越多,就越具体
信息越少,就越抽象

什么叫流?

比如:接 100L 的水,可以分10次接,一次接10L;也可以分20次接,一次接20L;也可以分1次接,一次性接完。接法有很多种,但最终的效果是一样的

文件流也是类似的:读写 100 字节的数据,可以分20次,每次读写5字节;也可以分1次读写,一次性读写完…
读写方式任意多种,但最终的结果都是把 100 字节的数据读写完毕


Java提供的 “流” API

Java标准库对于 “流” 进行了一系列的封装,提供了一组类来负责进行这些工作。
针对这么多类,大体可分为两大类别:

  1. 字节流
    字节为单位进行读写,一次最少读写 1 字节

    代表类:
    InputStream 输入
    OutputStream 输出

  2. 字符流
    字符为单位进行读写。
    比如:如果是以 utf8 来表示汉字,一个汉字为 3 字节;那么每次读写都得以 3 个字节为单位来进行读写,不能以其他字节数来读写(不然给你读取半个汉字?不可能吧)

    代表类:
    Reader 输入
    Write 输出


文件流读写文件内容

因为流这一概念是从操作系统中借过来的,所以读写文件内容在各种编程语言中,都是“固定套路“:

  1. 打开文件

  2. 关闭文件

  3. 读文件

  4. 写文件


InputStream 示例

InputStream 点进源码可以看到是一个抽象类,不可实例化

再谈为什么要加 抽象类这一概念
abstract 主要还是为了多一重 “校验”,因为这个抽象类我们是不希望它能够实例化的,就像 “单例模式” ,所以让编译器给我们再一次校验

所以我们实例化它的 “子类”,Java标准库中给我们提供了很多
![[Pasted image 20240118133828.png]]

我们选择 FileInputStream ,顾名思义,是从文件中

注:因为是 “” 文件,所以得先有文件,这里创建一个 test.txt 文件来作为示例。
![[Pasted image 20240118135644.png]]

.close() 可以理解是:释放文件的相关资源,当然这种写法是不对的,中间逻辑但凡出了问题,这个资源就释放不了了。

第一种写法:自己手动释放资源
![[Pasted image 20240118141616.png]]

第二种写法:Java的 try 操作还提供了另外一个版本:try with resources(带有资源的 try 操作)
一旦执行完 try 代码块,try自动调用 inputStreamclose() 方法
![[Pasted image 20240118141952.png]]


读文件

.read() 方法,有三种:
![[Pasted image 20240118143943.png]]

  1. 不带参数的 read() 方法:读取 1字节的数据,虽然返回值是 int 类型,但实际上是 byte,取值为 0 - 255,正好是1个字节的取值量。如果读取到文件末尾继续 read() 就会返回-1,正因为多了一个 -1,才会用 int 作为返回值。
    • 这种读取一个字节的数据,返回值为这个字节对应码表的数值。如第一个字节数值为 a,那么返回值就是对应 ASCII 码表的 97
      在这里插入图片描述

在这里插入图片描述

  1. read(byte[] buffer) ,最多读取 buffer.length 字节的数据到 b 中,返回实际读取到的数量;-1 代表已经读取完毕

    • 返回值为 buffer 数组的长度。
    • 假设 .txt 文件中存的是 111ab.cread(buffer) 操作就把该 .txt 文件的每个字节填充进 buffer 中,buffer 每个空间存的就是 对应ASCII码表的值,如图:
    • ![[Pasted image 20240119131443.png]]
  2. read(byte[] b, int off, int len) ,从 off 处开始读取,最多读取 len 个字节的数据;-1 代表已经读取完毕

    这里的 offoffset 偏移量的意思。

如图:off 处传1,len处传5。表示:从 buffer 数组的 1 下标位置开始读取,读取 5 个字节
![[Pasted image 20240119131700.png]]

注:使用 read 方法的时候,往往是定义一个内容为空的数组(不是null),把空的数组交给 readread内部对数组内容进行填充(读取到的内容放哪?放在我们所给的数组中)
![[Pasted image 20240118144811.png]]


示例1:将文件完全读完的两种方式

在 “当前目录” 下创建一个 test.txt 文件,随便输入几个字符,然后读取
相较之下,后一种的 IO 次数更少,性能更好

讨论IO时,一定要分清楚,I是I,O是O,两者是分开的。
这里的 read 站在内存的角度上看,就是 input,输入部分。带参数和不带参数的read 在这里是没有性能差别的。
但 output 时,站在 内存 的角度上看,第一个没有缓冲区,每次都要重新从硬盘读取,然后输出;第二个有缓冲区,已经一次性把数据从硬盘读取到内存中了,每次输出时就不用再从硬盘读取了,直接从内存取。
这就是为什么后一种IO次数更少,性能更好的原因

read()一次读一个。要知道:操作硬盘,本身就是一个低效的操作,而低效的操作,出现的次数越少越好。
![[Pasted image 20240119132141.png]]

read(byte[] buffer):一次性地,从头到尾地,将 buffer 数组填充 “满”,加上循环的话,最后一次填充满了之后,返回值不会是 -1,而是数组的长度;再次调用,就会返回 -1
![[Pasted image 20240119143334.png]]

![[Pasted image 20240119143340.png]]


示例二:读取汉字

byte 占 1 个字节,而一个汉字占3个字节(因为Java中是utf8编码,GBK一个汉字占2个字节,不要弄混),所以两个汉字需要用 6 个byte空间来存储。

如果要输出汉字,可以使用 String 的构造方法,然后输出字符串。这里Java是进行了特殊的处理,这个后续再表
![[Pasted image 20240119145616.png]]
![[Pasted image 20240119145629.png]]


写文件

注意!:写文件操作,在 new FileOutputStream 的时候,就会把文件中的内容清空
但也可以不清空,在文件内容的**下一行写入数据**

append 追加,设置为 true,就可以不清空内容了
![[Pasted image 20240119150536.png]]

方法和 read 类似,使用也是相似的:
![[Pasted image 20240119150353.png]]

还有两个额外需要注意的方法:特别注意 flush()
![[Pasted image 20240124125015.png]]


谈谈 OutputStreamWriterPrintWriter

![[Pasted image 20240124143010.png]]

其实第一步 new OutputStream 时就已经完成了输出工作,但 OutputStream 输出的时候在 “某些方面“ 不太方便

比如:输出之后换行,输出可以运算的内容。如图所示的 println / print / printf

要实现上面三个功能,就还需要通过其他类来 “加工” 一下,这些类就是 OutputStreamWriterPrintWriter,也就是如上图书写的顺序

PrintWriter 是以 ”字符流“ 写入的
OutputStreamWriter 是 “字符流” “字节流” 的桥梁(不是字节到字符)

所以具体流程为:PrintWriter 以 “字符流” 写入数据,随后通过 OutputStreamWriter 将写入的 ”字符流“ 数据转成 ”字节流“ 数据(此处内置了缓冲区),最后才将这些 ”字节流数据” 写入通过 OutputStream 从内存输出进文件内


Reader

Reader:大致用法都差不多,只不过这里是按字符char 来读取的
![[Pasted image 20240119200611.png]]

注意这里:一个汉字是3个字节,但 char 只占 2 个字节,为什么能正常存储?而且还能打印出汉字?

文件内容是按 utf8 来编码的,char 在读取时,会将 utf8 转成 unicode,每个 char 里存储的是对应的 unicode 的值; String 的构造方法,又可以基于 unicode 转换成 utf8。
总结:文件 utf8 --> char[] unicode --> String utf8

这个转换过程是在Java中封装好了的


Writer

使用方式也是相似的,一般是用第二个:一次写入一串字符串
第一个是一次写入一个字符
第三个是一次写入一个字符数组

![[Pasted image 20240119201523.png]]


Scanner 辅助输入

Scanner(System.in) 括号里面的,本质上就是一个 InputStream

示例:

![[Pasted image 20240119202544.png]]

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

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

相关文章

Practical User Research for Enterprise UX

2.1 Why It’s Hard to Get Support for Research in Enterprises 2.1.1 Time and Budget Instead of answering the question “What dowe gain if we do this research?”, ask instead “What do we stand to lose if we don’t do the research?” 2.1.2 Legacy Thinkin…

HMI界面:感官与体验俱佳的智能家居界面分享

Hello,我是大千UI工场,本期分享HMI人机交互界面在智能家居领域的案例,关注大千,学习N多UI干货,有设计需求,可以联络。 设计感官和体验俱佳智能家居的UI界面时,可以考虑以下几个方面:…

算法中关于数学的题目练习

算法中关于数学的题目练习 1、买不到的数目题目信息思路题解 2、蚂蚁感冒题目信息思路题解 3、饮料换购题目信息思路题解 1、买不到的数目 题目信息 思路 数学结论(证明略): p、q为正整数且互质,不能由p、q凑出来的最大的数为(p…

DNS服务正反解析

1.正向解析 1.配置基本 1.1防火墙配置 二者都要关闭 setenforce 0 systemctl stop firewalld #关闭防火墙 yum install bind -y #下载bind软件 客户端可以不用下 1.2服务端配置静态ip, ip a 查看网卡 nmcli c modify ens33 ipv4.method manual ipv4.addresses …

使用PaddleNLP UIE模型提取上市公司PDF公告关键信息

项目地址:使用PaddleNLP UIE模型抽取PDF版上市公司公告 - 飞桨AI Studio星河社区 (baidu.com) 背景介绍 本项目将演示如何通过PDFPlumber库和PaddleNLP UIE模型,抽取公告中的相关信息。本次任务的PDF内容是破产清算的相关公告,目标是获取受理…

第三百五十回

文章目录 1. 概要介绍2. 获取方法2.1 获取语言2.2 获取地址 3.示例代码3. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题"相关的内容,本章回中将介绍如何获取系统语言.闲话休提,让我们一起Talk Flutter吧。 1. 概要介绍 我们在本…

机试复习-4

1.string类 string类型和数值的转换 ※数值→字符串 to_string函数 //具体做法 int i1234; string gto_string(i);//这样就转成字符串1234了 //下面就是字符串转为数字&#xff0c;类似下面还有stof,stoi,stod string d "1289347647"; int j stoi(d); cout <…

Halcon 相机标定

文章目录 算子单相机标定单相机标定畸变的矫正 算子 gen_caltab 生成标定文件 gen_caltab(::XNum,YNum,MarkDist,DiameterRatio,CalTabDescrFile,CalTabPSFile :) 算子来制作一个标定板XNum 每行黑色标志圆点的数量。YNum 每列黑色标志圆点的数…

RAG近期发展综述

RAG简介 RAG全称为检索增强生成技术&#xff0c;其主要可以分为三部分&#xff0c;索引&#xff08;构建&#xff09;、检索以及生成&#xff0c;各个部分又可以进一步细分。 索引 索引阶段主要是构建知识库的过程&#xff0c;这里的知识库是泛指&#xff0c;包括了向量数据…

JAVA之HashMap详解

HashMap 1. 设计原理 HashMap 基于哈希表的 Map 接口实现&#xff0c;是以 key-value 存储形式存在&#xff0c;即主要用来存放键值对。HashMap 的实现不是同步的&#xff0c;这意味着它不是线程安全的。它的 key、value 都可以为 null&#xff0c;此外&#xff0c;HashMap 中…

sql语句学习(一)--查询

【有道云笔记】基本sql语句2—查询基础 数据库表结构 DROP TABLE IF EXISTS class; CREATE TABLE class (id int(11) NOT NULL AUTO_INCREMENT,class_num varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 班级号,class_name varchar(255) CHARACTE…

飞天使-k8s知识点21-kubernetes实操6-daemonset

文章目录 daemonsetservice endpoint pod 之间的关系service基于Service访问外部服务 daemonset DaemonSet 是 Kubernetes 中的一种资源对象&#xff0c;它确保在集群中的每个节点上都运行一个 Pod 的副本。这对于运行集群级别的守护进程&#xff08;例如日志收集器、监控代理…

Leetcode - 周赛384

目录 一&#xff0c;3033. 修改矩阵 二&#xff0c;3035. 回文字符串的最大数量 三&#xff0c;3036. 匹配模式数组的子数组数目 II 一&#xff0c;3033. 修改矩阵 这道题直接暴力求解&#xff0c;先算出每一列的最大值&#xff0c;再将所有为-1的区域替换成该列的最大值&am…

mysql 2-17

UNION关键字和UNION ALL 自然连接 USING使用 函数 单行函数 基本函数 三角函数 指数和对数 进制间的转换 字符串函数 时间和日期函数 计算日期和时间的函数 日期的格式化和解析 流程控制函数

输入输出自定义映射矩阵(数据结构树)

输出自定义FC其它算法实现,可以参考下面文章: https://rxxw-control.blog.csdn.net/article/details/125994252https://rxxw-control.blog.csdn.net/article/details/125994252下面我们看下我们的控制要求。在学习本篇博客之前大家可以熟悉下数据结构图的概念和存储知识,链…

【复合多尺度熵与特征提取】一文看懂“复合多尺度熵”——复合多尺度样本熵、模糊熵、排列熵、包络熵、功率谱熵、能量熵、奇异谱熵及其MATLAB实现

在上一篇文章中&#xff0c;我们讲了多尺度熵的原理及MATLAB实现。 本篇要讲的是多尺度熵的一个改进特征提取方法——复合多尺度熵&#xff08;Composite Multiscale Entropy, CMSE&#xff09;。复合多尺度熵方法不仅继承了多尺度熵在揭示时间序列多尺度复杂性方面的优势&…

【Python--Web应用框架大比较】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Django Django太重了&#xff0c;除了web框架&#xff0c;自带ORM和模板引擎&#xff0c;灵活和自由度不…

定时器外部时钟

一、相较于内部时钟中断改动&#xff1a; 1.Timer.c RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin GPIO_Pin_…

ACM题解Day4 | Boring Non-Palindrome ,Mental Rotation ,so Easy

学习目标&#xff1a; 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门算法 &#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d; ☆*: .&#xff61;. o(≧▽…

GuitarPro8激活许可证24位下载

Guitar Pro是一款专业的吉他制谱软件&#xff0c;现在已更新至Guitar Pro8&#xff0c;新增了支持添加音频轨道、支持嵌套连音符、直观的效果器视图、让指法一目了然的音阶示意图等实用新功能。下面我们来看Guitar Pro8 如何安装激活。 Guitar Pro 8.1官方中文解锁版如何安装 …