【Java】文件操作与IO

文件操作与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]]

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

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

相关文章

进程状态

广义概念: 从广义上来讲,进程分为新建、运行、阻塞、挂起、退出五个状态,其中新建和退出两个状态可以直接理解字面意思。 运行状态: 这里涉及到运行队列的概念,CPU在读取数据的时候,需要把内存中的进程放入…

软件工程师,OpenAI Sora驾到,快来围观

概述 近期,OpenAI在其官方网站上公布了Sora文生视频模型的详细信息,展示了其令人印象深刻的能力,包括根据文本输入快速生成长达一分钟的高清视频。Sora的强大之处在于其能够根据文本描述,生成长达60秒的视频,其中包含&…

太炸了!Sora深夜发布!网友:我要失业了

2022年末,OpenAI聊天机器人ChatGPT的面世无疑成为了引领人工智能浪潮的标志性事件,宣告了新一轮科技革命的到来。无论是聊天娱乐、教育学习,还是工作生产、医疗健康等领域,人工智能正以前所未有的速度渗透到我们生活的方方面面。 …

深入解析ESP32C3(3)- bootloader启动流程

ESP32C3启动流程可以分为如下3 个步骤: 一级引导程序(PBL):被固化在了ESP32-C3 内部的ROM 中,它会从flash 的0x0 偏移地址处加载二级引导程序至RAM (IRAM & DRAM) 中。二级引导程序(SBL):从flash 中加载分区表和主程序镜像至…

什么是数据同步利器DataX,如何使用?

转载至我的博客 https://www.infrastack.cn ,公众号:架构成长指南 今天给大家分享一个阿里开源的数据同步工具DataX,在Github拥有14.8k的star,非常受欢迎,官网地址:https://github.com/alibaba/DataX 什么…

【Java程序设计】【C00265】基于Springboot的地方废物回收机制管理系统(有论文)

基于Springboot的地方废物回收机制管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的地方废物回收机构管理系统 本系统分为管理员功能模块以及员工功能模块。 管理员功能模块:管理员登录系统后…

spring boot3登录开发-1(整合jwt)

⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 🌊山高路远,行路漫漫,终有归途。 目录 前置条件 jwt简介 导依赖 编写jwt工具类 1.配置项直接嵌入代码,通过类名.静态方法使用 2.配置项写到…

算法刷题:无重复字符的最长字串

无重复字符的最长字串 .题目链接题目详情算法原理题目解析滑动窗口定义指针进窗口判断出窗口更新结果 我的答案 . 题目链接 无重复字符的最长字串 题目详情 算法原理 题目解析 首先,为了使字符串遍历的更加方便,我们选择将字符串转换为数组 题目要求子串中不能有重复的字符…

LaTeX中的documentclass命令:指定文档的类型和整体布局

诸神缄默不语-个人CSDN博文目录 documentclass 是 LaTeX 中一个基础且重要的命令,用于定义文档的整体布局和样式。这个命令告诉 LaTeX 编译器文档是属于哪一类的,比如是文章、报告、书籍等,每一类都有其预定义的格式和结构。 文章目录 基本语…

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-Swagger框架集成

Swagger是什么? Swagger是一个规范且完整API文档管理框架,可以用于生成、描述和调用可视化的RESTful风格的 Web 服务。Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就…

JDBC 核心 API

引入 mysql-jdbc 驱动 驱动 jar 版本的选择:推荐使用 8.0.25,省略时区设置java 工程导入依赖 项目创建 lib 文件夹导入驱动依赖 jar 包jar 包右键 - 添加为库 JDBC 基本使用步骤 注册驱动获取连接创建发送 sql 语句对象发送 sql 语句,并获…

清华AutoGPT:掀起AI新浪潮,与GPT4.0一较高下

引言: 随着人工智能技术的飞速发展,自然语言处理(NLP)领域迎来了一个又一个突破。最近,清华大学研发的AutoGPT成为了业界的焦点。这款AI模型以其出色的性能,展现了中国在AI领域的强大实力。 目录 引言&…

字符串拼接 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C 题目描述 给定 M 个字符( a-z ) ,从中取出任意字符(每个字符只能用一次)拼接成长度为 N 的字符串,要求相同的字符不能相邻。 计算出给定的字符列表…

突发!亚马逊创始人贝索斯抛售60亿美元股票,外网疑其或加仓比特币

号外:2.16教链内参《内参:OpenAI Sora惊艳发布,加密圈有人获利超700倍》 前世界首富、全球知名电商平台亚马逊(amazon)创始人杰夫贝索斯(Jeff Bezos)最近一周以来接连抛售自家公司股票&#xff…

BulingBuling[Beyond the To-Do List] - 《让金钱为你服务》 [ Make Money Work for You ]

与《财务自由: 赚到足够的钱的有效方法》作者Grant的简短访谈 让钱为你工作 超越待办事项清单 主持人:Erik Fisher Make Money Work for You Beyond the To-Do List Hosted by Erik Fisher 与Erik Fisher一起探索如何确定你生活中最大的财务杠杆以及使用它们的最佳方…

【Linux系统化学习】文件重定向

目录 文件内核对象 文件描述符的分配规则 重定向 重定向的概念 dup2系统调用 输出重定向 追加重定向 输入重定向 stderr解析 重定向到同一个文件中 分离常规输出和错输出 文件内核对象 上篇文章中我们介绍到了操作系统中的文件,操作系统为了方…

什么是智慧公厕,智慧公厕有哪些功能

1.什么是智慧公厕? 随着智慧城市的快速发展,公共厕所作为城市基础设施的一部分,也在逐步升级转型。那么,什么是智慧公厕?智慧公厕作为智慧城市的重要组成部分,将公共厕所的建设、设计、使用、运营和管理等…

报错405(errAxiosError: Request failed with status code 405)

errAxiosError: Request failed with status code 405 前端调用接口的方法跟后台定义接口的方法不一致

docker (四)-docker网络

默认网络 docker会自动创建三个网络,bridge,host,none bridge桥接网络 如果不指定,新创建的容器默认将连接到bridge网络。 默认情况下,使用bridge网络,宿主机可以ping通容器ip,容器中也能ping通宿主机。 容器之间只…

UE4学习笔记 FPS游戏制作5 动画蒙太奇制作开枪动画

创建一个蒙太奇 选择角色的骨骼,并重命名 编辑蒙太奇 将我们需要的动画拖动到Default下的两个白杠的上边那个里 然后在下方的Sections节点中,点击Preview后的Default,选中后,再点击PreviewAllScetions上百年的长的绿色的Defalut&…