文件操作和InputStream,OutputStream的用法

“他越拧巴,我越喜欢!”

文件: 

此处谈到的文件,本身有很多的含义。

狭义上的文件,特指 硬盘上的文件(以及保存文件的目录)。

广义上的文件,计算机上的很多硬件设备,软件资源,在操作系统中都会被视为“文件”。

硬盘和内存对比:

  1. 硬盘的存储空间大,内存小
  2. 硬盘的访问速度慢,内存快 (硬盘访问速度慢,和它硬件的物理结构有关)
  3. 硬盘的成本低,内存高
  4. 硬盘能持久化存储,内存断电后数据会丢失

树型结构组织 和 目录:

随着文件越来越多,对文件的系统管理也被提上了⽇程,如何进行文件的组织呢,⼀种合乎⾃
然的想法出现了,就是按照层级结构进⾏组织 ⸺ 也就是我们数据结构中学习过的树形结构。这样,⼀种专门用来存放管理信息的特殊文件诞⽣了,也就是我们平时所谓⽂件夹(folder)或者⽬录
(directory)的概念。

目录: 用于组织文件的容器,可以包含文件和其他目录(子目录)。

基于上述的结构,就可以找到,某个文件在硬盘上的具体位置。

这一串目录结构,就描述了文件所在的位置。文件中,就约定使用分隔符,分隔目录。

\(反斜杠)      /(斜杠) 绝大部分系统,都是使用 / 作为目录的分隔符的,只有windows是既能够使用 / 也能够使用 \.

路径:

可以认为是文件的一种身份标识,通过标识,区分出唯一的一个文件.

1.绝对路径:

从盘符开始,一直到文件名结束.

D:\JavaEE(primer)\java-ee\Io\bug1.txt

2.相对路径:

说到相对路径,必然有一个"参考系",就是有一个"基准路径"或"工作路径".

如果说基准路径不同的话,对应的相对路径也是不同的.

拿上面的D:\JavaEE(primer)\java-ee\Io\bug1.txt举例:

如果约定以D:\JavaEE(primer)为基准目录  ->  相对路径为: .\java-ee\Io\bug1.txt

如果约定以D:\JavaEE(primer)\java-ee为基准目录 ->  相对路径为: .\Io\bug1.txt

文件的类型:

文本文件:当前文件里存储的所有内容,都是"文本"(合法的字符).

字符的编码方式(字符集):UTF-8 GBK字符编码

二进制文件:对应的,如果文件内容,在字符集对应的表格中,不可查,此时就是 二进制文件.

(简单粗暴的方式,直接使用记事本打开文件,如果打开之后不是乱码,就是文本文件,否则就是二进制文件).

文件的操作:

1.文件系统的操作(创建文件,删除文件,创建目录,重命名文件,判定文件是否存在.......)

Java中提供了 FILE 类,进行文件系统操作,这个对象,会使用"路径"初始化.从而标识一个具体的文件(这个文件可以存在也可以不存在).

构造方法
  • File(String pathname): 根据路径名字符串创建一个新File实例。
  • File(String parent, String child): 根据父路径名和子路径名创建新的File实例。
  • File(File parent, String child): 根据父File对象和子路径名创建新的File实例。
常用方法
  1. 文件和目录的创建、删除

    • boolean createNewFile(): 创建一个新文件,如果文件已经存在则返回false。
    • boolean mkdir(): 创建一个新目录,只有在其父目录存在的情况下才会创建成功。
    • boolean mkdirs(): 创建一个新目录,包括任何必需但不存在的父目录。
    • boolean delete(): 删除文件或目录,只有在目录为空时可以删除。
    • void deleteOnExit():根据File对象,标注我呢间将被删除,删除的动作会到JVM运行结束时才会进行。
  2. 文件和目录的查询

    • boolean exists(): 测试文件或目录是否存在。
    • boolean isDirectory(): 测试此抽象路径名表示的文件是否是一个目录。
    • boolean isFile(): 测试此抽象路径名表示的文件是否是一个标准文件。
    • boolean isHidden(): 测试此抽象路径名表示的文件是否是一个隐藏文件。
    • String getName(): 获取文件或目录的名称。
    • String getPath(): 获取文件或目录的路径。
    • String getAbsolutePath(): 获取文件或目录的绝对路径。
    • String getcanonicalPath(): 返回File对象的修饰过的绝对路径
    • long length(): 获取文件的字节长度。
  3. 文件和目录操作

    • boolean renameTo(File dest): 将该文件或目录重命名为指定的目标File。
    • String[] list(): 获取目录中的文件和子目录名称的字符串数组。
    • File[] listFiles(): 获取目录中的文件和子目录的File数组。

下面我们来看看部分方法的用法与效果:


观察 get 系列的特点和差异
public class Demo1 {public static void main(String[] args) throws IOException {//绝对路径File file =  new File("D:\\JavaEE(primer)\\java-ee\\Io\\bug1.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.getCanonicalPath());}
}

注意:创建文件,很可能会抛出异常的

(1)硬盘的空间不够了。

(2)没有权限,确保你具有操作的权限,才能进行,对于文件的权限,典型的就是读和写。


普通文件的创建、删除
public class Demo2 {public static void main(String[] args) throws IOException {File file = new File("./hello.txt");boolean ok = file.createNewFile();System.out.println(ok);System.out.println(file.exists());System.out.println(file.isFile());System.out.println(file.isDirectory());}
}

 

public class Demo3 {public static void main(String[] args) {File file = new File("./hello.txt");boolean ok = file.delete();System.out.println(ok);}
}

下面我们来看一看 void deleteOnExit()与boolean delete()有什么不同:

 


列出file对象下的文件名
public class Demo5 {public static void main(String[] args) {File file = new File("./src");System.out.println(Arrays.toString(file.list()));System.out.println(Arrays.toString(file.listFiles()));}
}

如果直接使用list /listFiles 只能看到当前目录中的内容,如果想看到某个目录中所有的目录和文件,就需要递归来完成了!

public class Demo7 {public static void main(String[] args) {File file = new File("./");scan1(file);}private static void scan1(File file) {//先判断是不是目录if(!file.isDirectory()) {return ;}//列出当前目录中包含的内容File[] files = file.listFiles();//不存在路径/空目录if(files == null || files.length == 0) {return;}//打印当前目录System.out.println(file.getAbsolutePath());for (File f:files) {//如果是普通文件就直接打印文件路径if(f.isFile()) {System.out.println(f.getAbsolutePath());//是目录,就继续进行递归}else {scan1(f);}}}
}


观察目录的创建

 


观察文件名的重命名


 文件内容的读写-数据流:

读文件和写文件,都是操作系统提供了 api,java也进行了封装.

"文件流"/"IO流"

水流的特点:                                                                             IO流的特点:

我要通过水龙头,接100ml的水:                                        我要从文件中读取100字节的数据

1.直接一口气,把100ml水接完                                          1.直接一口气,把100字节读完

2.一次接50ml,分两次接完                                                2.一次读50字节,分两次

3.一次接10ml,分10次接完                                                3.一次读10字节,分10次

...............................................                                           ..........................................................

1.字节流(二进制) 读写的基本单位,就是字节 

InputStream        OutputStream

2.字符流(文本)读写的基本单位,就是字符

Reader                 Writer

上述的这四个类,都是“抽象类”,实际上真正干活的不是这四个。java中实现了提供了很多很多的类,实现了上述的这四个抽象类。

凡是类的名字一 Reader Writer结尾的,就是实现了reader 和 Writer的字符流对象,凡是类的名字以 InputStream 和 OutputStream结尾的,就是实现了 InputStream 和 OutputStream 的字符流对象。

以下是 InputStream 类的一些常用方法:

  1. int read(): 读取一个字节的数据,返回一个整数(0-255),如果达到流的末尾,则返回 -1。

  2. int read(byte[] b): 读取多个字节的数据,将读取的数据存储到字节数组 b 中,返回读取的字节数,如果达到流的末尾,则返回 -1。

  3. int read(byte[] b, int off, int len): 从输入流中读取最多 len 个字节的数据,并将其存储在数组 b 从偏移量 off 开始的位置。返回实际读取的字节数,如果达到流的末尾,则返回 -1。

  4. void close(): 关闭输入流并释放与该流相关联的所有资源。

public class Demo10 {public static void main(String[] args) throws IOException {//这里("./ret.txt")可以指定绝对路径,也可以是相对路径,还可以是FIle对象InputStream inputStream = new FileInputStream("./ret.txt");//此处隐含一个操作“打来文件”,file open,针对文件进行读写,务必需要先打开(操作系统,基本要求)//关闭inputStream.close();}
}

如果不使用close()关闭,会怎么样呢?

打开文件,其实就是在 该进程的 文件描述符表 中,创建一个新的表项。描述了该进程,都要操作哪些文件,文件描述符表,可以认为是一个数组。数组中的每个元素就是一个 struct file 对象,每个结构体就描述了对应操作的文件的信息,数组的下标,就称为“文件描述符”。

每次打开一个文件,就相当于在一个数组上占用了一个空间,而在系统内核中,文件描述符表数组是固定长度&&不可扩容的。

除非主动调用close,关闭文件,此时才会释放出空间。否则,如果代码里一直打开,没有去进行关闭,就会使这里的资源越来越少,数组的空间被占满之后,后续在进行打开文件就会失败!

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class Demo11 {public static void main(String[] args) {InputStream inputStream = null;try {inputStream = new FileInputStream("./ret.txt");} catch (FileNotFoundException e) {e.printStackTrace();}finally {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}

这种写法,虽然能够确保严谨,但是比较麻烦,下面给出一种简单&&可靠的办法!

public class Demo12 {public static void main(String[] args) {try(InputStream inputStream = new FileInputStream("./ret.txt")) {}catch(IOException e) {e.printStackTrace();}}
}

 这样的写法之下,不必写finally也不必写close,这里的()中创建的资源(可以是多个,中间用;)try的()执行完毕,最终都会自动执行close()。

必须实现了Closeable接口的类,才可以放到try()里面!

我们先看看ret.txt这个这个文件里面有什么内容:

里面只有一个字符h.

下面进行读取ret.text这个文件里面的内容。 

public class Demo14 {public static void main(String[] args) {try(InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {int b = inputStream.read();if (b == -1) {// 读取完毕了break;}// 表示字节, 更习惯使用 十六进制 打印显示.System.out.printf("0x%x\n", b);}}catch (IOException e) {e.printStackTrace();}}
}

 h的十六进制就是68,所以说正确的读了出来!

下面,我将test.txt这个文件里面的内容改成“难受”,然后进行读取操作。这次不是一次只读取一个字节,而是读取多个。

public class Demo13 {public static void main(String[] args) {try(InputStream inputStream = new FileInputStream("./ret.txt")) {while(true) {byte[] buffer = new byte[1024];//n表示实际上读取到了多少个字节int n = inputStream.read(buffer);if(n == -1) {break;}for(int i = 0;i < n;i++) {System.out.printf("0x%x\n",buffer[i]);}}}catch (IOException e) {e.printStackTrace();}}
}

其中的 inputStream.read(buffer);此处是把buffer形参当成了“输出型参数”,这个操作就会把硬盘中读到的对应的数据,填充到buffer内存的字节数组中。(这个过程就像你是食堂打饭时,把你手中的饭盒交给食堂阿姨,阿姨打满饭菜之后交给你)

 读取展示完之后,那么写操作也是类似的啦。

可以发现,我们之前的文件中是有其他内容的,在进行写入之后,之前的内容被覆盖了。如果不想被覆盖,可以在实例对象中写上 true 。 

有了上述的InputStream he OutputStream操作的展示之后,后面的Reader 和 Writer 展示,我就仅仅展示一些代码来看看咯。 

Reader:

Writer: 

相信对于大家来说很简单吧。那么以上呢,就是今天的内容了,我们下一期再见吧。

“无论前方的路有多艰难,只要我们保持对未来的信心,就一定能克服一切困难。让我们一起在追梦的旅程中不断前行!”

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

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

相关文章

idea2021git从dev分支合并到主分支master

1、新建分支 新建一个名称为dev的分支&#xff0c;切换到该分支下面&#xff0c;输入新内容 提交代码到dev分支的仓库 2、切换分支 切换到主分支&#xff0c;因为刚刚提交的分支在dev环境&#xff0c;所以master是没有 3、合并分支 点击push&#xff0c;将dev里面的代码合并到…

【Web】御网杯信息安全大赛2024 wp(全)

目录 input_data admin flask 如此多的FLAG 一夜醒来之全国CTF水平提升1000倍&#x1f60b; input_data 访问./.svn后随便翻一翻拿到flag admin dirsearch扫出来 访问./error看出来是java框架 测出来是/admin;/路由打Spring View Manipulation(Java)的SSTI https:/…

C++容器list底层迭代器的实现逻辑~list相关函数模拟实现

目录 1.两个基本的结构体搭建 2.实现push_back函数 3.关于list现状的分析&#xff08;对于我们如何实现这个迭代器很重要&#xff09; 3.1和string,vector的比较 3.2对于list的分析 3.3总结 4.迭代器类的封装 5.list容器里面其他函数的实现 6.个人总结 7.代码附录 1.两…

Selenium with Python学习笔记整理(网课+网站持续更新)

本篇是根据学习网站和网课结合自己做的学习笔记&#xff0c;后续会一边学习一边补齐和整理笔记 官方学习网站在这获取&#xff1a; https://selenium-python.readthedocs.io/getting-started.html#simple-usage WEB UI自动化环境配置 (推荐靠谱的博客文章来进行环境配置,具…

Fyne ( go跨平台GUI )中文文档- 架构 (八)完结

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

《深度学习》PyTorch 手写数字识别 案例解析及实现 <下>

目录 一、回顾神经网络框架 1、单层神经网络 2、多层神经网络 二、手写数字识别 1、续接上节课代码&#xff0c;如下所示 2、建立神经网络模型 输出结果&#xff1a; 3、设置训练集 4、设置测试集 5、创建损失函数、优化器 参数解析&#xff1a; 1&#xff09;para…

ArcGIS10.2/10.6安装包下载与安装(附详细安装步骤)

相信从事地理专业的小伙伴来说&#xff0c;应该对今天的标题不会陌生。Arcgis是一款很常用的地理信息系统软件&#xff0c;主要用于地理数据的采集、管理、分析和展示。目前比较常见的版本有ArcGIS 10.2和ArcGIS 10.6。 不可否认&#xff0c;Arcgis具有强大的地图制作、空间分…

DataGrip在Windows和MacOS平台上的快捷键

0. 背景信息 No.说明1测试DataGrip版本号 : 2024.2.2 1. Windows下快捷键 2. MacOS下快捷键

CentOS Stream 9部署Redis

1、安装Redis sudo dnf install redis 2、启动Redis服务 sudo systemctl start redis 3、设置Redis开机自启 sudo systemctl enable redis 4、打开Redis配置文件&#xff1a; sudo vi /etc/redis/redis.conf 在配置文件中找到并修改以下两行&#xff0c;确保密码验证功能已启…

Docker 容器技术:颠覆传统,重塑软件世界的新势力

一、Docker简介 什么是docker Docker 是一种开源的容器化平台&#xff0c;它可以让开发者将应用程序及其所有的依赖项打包成一个标准化的容器&#xff0c;从而实现快速部署、可移植性和一致性。 从功能角度来看&#xff0c;Docker 主要有以下几个重要特点&#xff1a; 轻量…

数据结构——串的模式匹配算法(BF算法和KMP算法)

算法目的&#xff1a; 确定主串中所含子串&#xff08;模式串&#xff09;第一次出现的位置&#xff08;定位&#xff09; 算法应用&#xff1a; 搜索引擎、拼写检查、语言翻译、数据压缩 算法种类&#xff1a; BF算法&#xff08;Brute-Force&#xff0c;又称古典的…

web基础—dvwa靶场(七)SQL Injection

SQL Injection&#xff08;SQL注入&#xff09; SQL Injection&#xff08;SQL注入&#xff09;&#xff0c;是指攻击者通过注入恶意的SQL命令&#xff0c;破坏SQL查询语句的结构&#xff0c;从而达到执行恶意SQL语句的目的。SQL注入漏洞的危害是巨大的&#xff0c;常常会导致…

『功能项目』QFrameWorkBug关联Slot(插槽)【67】

我们打开上一篇66QFrameWorkBug拖拽功能的项目&#xff0c; 本章要做的事情是关联插槽Slot 修改脚本&#xff1a;UISlot.cs 修改脚本&#xff1a;UGUICanvas.cs 此时关联Slot已经完成 接下来的文章内容&#xff1a; 1.QFrameWork扔到地上UGUI 2.位置存储功能 3.点击名称寻…

VMware ESXi 8.0U3b macOS Unlocker OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版)

VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版) 发布 ESXi 8.0U3 集成驱动版&#xff0c;在个人电脑上运行企业级工作负载 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-8-u3-sysin/&#xff0c;查看最新版…

10.3拉普拉斯金字塔

实验原理 拉普拉斯金字塔&#xff08;Laplacian Pyramid&#xff09;是一种图像表示方法&#xff0c;常被用于图像处理和计算机视觉领域。它是基于高斯金字塔的一种变换形式&#xff0c;主要用于图像融合、图像金字塔的构建等场景。下面简要介绍拉普拉斯金字塔的基本原理。 高…

【优选算法之二分查找】No.5--- 经典二分查找算法

文章目录 前言一、二分查找模板&#xff1a;1.1 朴素二分查找模板1.2 查找区间左端点模板1.3 查找区间右端点模板 二、二分查找示例&#xff1a;2.1 ⼆分查找2.2 在排序数组中查找元素的第⼀个和最后⼀个位置2.3 搜索插⼊位置2.4 x 的平⽅根2.5 ⼭脉数组的峰顶索引2.6 寻找峰值…

实现人体模型可点击

简化需求&#xff1a;实现项目内嵌人体模型&#xff0c;实现点击不同部位弹出部位名称 一&#xff1a;优先3d&#xff0c; 方案&#xff1a;基于three.js&#xff0c;.gltf格式模型&#xff0c;vue3 缺点&#xff1a;合适且免费的3d模型找不到&#xff0c;因为项目对部位有要…

【记录】Excel|不允许的操作:合并或隐藏单元格出现的问题列表及解决方案

人话说在前&#xff1a;这篇的内容是2022年5月写的&#xff0c;当时碰到了要批量处理数据的情况&#xff0c;但是又不知道数据为啥一直报错报错报错&#xff0c;说不允许我操作&#xff0c;最终发现是因为存在隐藏的列或行&#xff0c;于是就很无语地写了博客&#xff0c;但内容…

Java笔试面试题AI答之单元测试JUnit(5)

文章目录 25. 简述什么是Junit 忽略测试&#xff08;Ignore Test&#xff09;&#xff1f;一、基本概念二、使用方法三、注意事项四、示例 26. 简述什么是Junit 超时测试&#xff08;Timeout Test&#xff09;&#xff1f;Junit 超时测试的主要特点包括&#xff1a;实现方式&am…

全国832个贫困县名单及精准扶贫脱贫数据(2016-2020.11)

自党的十八大以来&#xff0c;通过全党全国各族人民的共同努力&#xff0c;中国成功实现了现行标准下9899万农村贫困人口的全部脱贫&#xff0c;832个贫困县全部摘帽。 摘帽名单 2016年-2020.11全国832个贫困县名单及精准扶贫脱贫数据整理&#xff08;大数据&#xff09;https…