文件操作和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.xdnf.cn/news/146862.html

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

相关文章

pick你的第一个人形机器人——青龙强化学习环境测试

文章目录 一、环境配置二、开始训练三、训练成果 最近感受到的大趋势是具身智能&#xff0c;强化学习&#xff0c;模仿学习做人形机器人&#xff0c;这个赛道很火&#xff0c;颇有前些年全力投入做自动驾驶的架势&#xff0c;正好最近用强化学习解决POMDP问题接触到了强化学习&…

怎么检查cuda是否安装成功(以及查看cuda的安装位置)

方法一&#xff1a; winr&#xff0c;再cmd&#xff0c;再在命令行中输入 nvcc -V 可以查看版本信息 方法二&#xff1a; winr&#xff0c;再cmd&#xff0c;再在命令行中输入 nvidia-smi 可以查看版本信息 方法三&#xff1a; 使用python,pytorch代码 import torch # 如果p…

Unet改进42:添加ACConv2d|使用一维非对称卷积来增强平方卷积核

本文内容:在不同位置添加ACConv2d 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 由于在给定的应用环境中设计合适的卷积神经网络(CNN)架构通常需要大量的人工工作或大量的GPU时间,研究社区正在征求架构中立的CNN结构,它可以很容易地插入到多个成熟的架…

C++:数组与字符串

一、数组 数组是一种存储若干元素的数据类型&#xff0c;在诸多编程语言中存在&#xff0c;其显著的特点是元素通常是在物理层面上连续存储的&#xff08;逻辑上的数组&#xff0c;比如链表&#xff0c;可能不是&#xff09;&#xff0c;并且具有极快的元素访问速度。 数组通常…

Spring Cloud Alibaba-(5)Seata【分布式事务】

Spring Cloud Alibaba-&#xff08;1&#xff09;搭建项目环境 Spring Cloud Alibaba-&#xff08;2&#xff09;Nacos【服务注册与发现、配置管理】 Spring Cloud Alibaba-&#xff08;3&#xff09;OpenFeign【服务调用】 Spring Cloud Alibaba-&#xff08;4&#xff09;Sen…

P1516 青蛙的约会(exgcd以及相关结论)

非常好的题&#xff0c;适合入门拓展欧几里得算法以及相关结论。 结论 ax by gcd(a,b) gcd(b,a%b) 由此递归求解即可。 int exgcd(int a,int b,int &x,int &y){// 求解 ax by gcd(a,b)if(!b){x 1,y 0;return a;}int g exgcd(b,a%b,x,y);int temp x;x y…

NLP 序列标注任务核心梳理

句向量标注 用 bert 生成句向量用 lstm 或 bert 承接 bert 的输出&#xff0c;保证模型可以学习到内容的连续性。此时 lstm 输入形状为&#xff1a; pooled_output.unsqueeze(0) (1, num_sentence, vector_size) 应用场景 词性标注句法分析 文本加标点 相当于粗粒度的分词任…

8590 队列的应用——银行客户平均等待时间

### 思路 1. **初始化队列**&#xff1a;使用InitQueue函数初始化一个队列&#xff0c;用于存储客户的到达时刻和办理时间。 2. **读取输入**&#xff1a;读取客户总人数和每个客户的到达时刻及办理时间。 3. **模拟业务办理**&#xff1a; - 维护一个当前时间变量currentTi…

【路径规划】 红嘴蓝鹊优化器:一种用于2D/3D无人机路径规划和工程设计问题的新型元启发式算法

摘要 本文提出了一种新型元启发式算法——红嘴蓝鹊优化器&#xff08;RBMO&#xff09;&#xff0c;用于解决2D和3D无人机路径规划以及复杂工程设计问题。RBMO灵感来源于红嘴蓝鹊的群体合作行为&#xff0c;包括搜索、追逐、捕猎和食物储藏。该算法通过模拟这些行为&#xff0…

模板:JDBC 连接数据库并实现 CRUD

目录 前期准备&#xff1a; 1. 连接数据库 1.1 第一种 1.2 第二种 2. 增加 3. 修改 4. 删除 5. 查询 5.1 查询某个记录 5.2 查询单列数据 使用时&#xff0c;直接复制再修改一些数据即可&#xff1b; 声明&#xff1a;在对文件/变量命名时&#xff0c;没有做到见名知…

CompletableFuture如何优雅处理异步任务超时!妙就完了

文章目录 1. 主要解决哪些业务痛点&#xff1f;2. 流程分析3. 上代码4. 总结一波 1. 主要解决哪些业务痛点&#xff1f; 小强最近一直没打黑神话悟空&#xff0c;闷闷不乐的&#xff0c;我问咋回事&#xff0c;最近有啥烦心事么? 他不爽的跟我说了当他CompletableFuture进行…

css基础知识笔记

一言&#xff1a; “放任误解就是撒谎。” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;CSS基础教程0.文本样式基础1. CSS选择器2. CSS布局技巧3. 响应式设计4. Emmet语法 总结 前言 写在开始&#xff1a; 今天来看一眼CSS基础知识。 好几天没更新了 先更一篇 文章有…

华为OD机试 - 需要打开多少监控器(Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

2024年最新网络协议分析器Wireshark抓包详细教程(更新中)

网络协议分析器 Wireshark 安装 Wireshark 是一个功能强大的网络协议分析器&#xff0c;早期叫作 Ethereal。它主要用于捕获网络数据包&#xff0c;并对这些数据包进行详细的解析和分析&#xff0c;帮助用户深入了解网络通信的细节。它支持多种网络协议&#xff0c;并提供详细…

银河麒麟桌面操作系统如何添加WPS字体

银河麒麟桌面操作系统如何添加WPS字体 1、使用场景2、操作方法步骤一&#xff1a;下载字体文件步骤二&#xff1a;打开终端步骤三&#xff1a;进入字体文件所在目录步骤四&#xff1a;拷贝字体文件到WPS字体目录步骤五&#xff1a;更新字体缓存步骤六&#xff1a;重启WPS Offic…

uni-app-通过vue-cli命令行快速上手

环境安装 全局安装 vue-cli npm install -g vue/cli创建uni-app 使用正式版&#xff08;对应HBuilderX最新正式版&#xff09; vue create -p dcloudio/uni-preset-vue my-project使用alpha版&#xff08;对应HBuilderX最新alpha版&#xff09; vue create -p dcloudio/uni-p…

Linux常用命令;Linux常用软件;Linux权限

一&#xff0c;常用命令 是人向计算机发送指令的语言。 命令的格式&#xff1a; 命令 [选项] [参数] 1、ls 展示当前目录下文件的命令 1、-l 展示详细信息。还有另外一种写法&#xff1a;ll&#xff08;字母 LL 小写&#xff09; 2、-S 按照文件大小倒序展示 3、-t…

1952. 三除数

目录 一&#xff1a;题目&#xff1a; 二&#xff1a;代码&#xff1a; 三&#xff1a;结果&#xff1a; 一&#xff1a;题目&#xff1a; 给你一个整数 n 。如果 n 恰好有三个正除数 &#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在整数 k &a…

【软件测试】性能测试-概念篇

目录 &#x1f334;什么是性能测试 &#x1f333;常见性能测试指标 &#x1f6a9;并发数 &#x1f6a9;吞吐量 &#x1f6a9;吞吐量分类 &#x1f3c0;按照请求分类:TPS和QTS &#x1f3c0;按照网络数据包划分:KB &#x1f6a9;响应时间 &#x1f6a9;资源利用率 &am…

SpringBoot启动流程之运行时监听器

SpringBoot启动过程&#xff1a; 上一节我们讨论SpringApplication实例化的过程&#xff0c;也就是上图1-5步骤&#xff0c;本节我们讨论6-9的关键步骤&#xff0c;现在主要讲是run方法里面的过程 /*** 启动方法* param args* return*/public ConfigurableApplicationContext …